Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
提交反馈
为 GitLab 提交贡献
登录
切换导航
iBiz4j Spring R7
项目
项目
详情
动态
版本
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
iBiz-R7后台标准模板
iBiz4j Spring R7
提交
eedfa55f
提交
eedfa55f
编写于
7月 09, 2020
作者:
zhouweidong
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
审计
上级
4dff20d9
变更
9
显示空白字符变更
内嵌
并排
正在显示
9 个修改的文件
包含
700 行增加
和
0 行删除
+700
-0
%DE%.java.ftl
...ava/%SYS_PKGPATH%/core/%MOD_PKGPATH%/domain/%DE%.java.ftl
+42
-0
20200709124030_init_ibzaudit.xml.ftl
.../liquibase/changelog/20200709124030_init_ibzaudit.xml.ftl
+27
-0
Audit.java.ftl
...rc/main/java/%SYS_PKGPATH%/util/annotation/Audit.java.ftl
+21
-0
AuditAspect.java.ftl
.../main/java/%SYS_PKGPATH%/util/aspect/AuditAspect.java.ftl
+170
-0
IBZDataAudit.java.ftl
...main/java/%SYS_PKGPATH%/util/domain/IBZDataAudit.java.ftl
+36
-0
DEFieldCacheMap.java.ftl
...n/java/%SYS_PKGPATH%/util/helper/DEFieldCacheMap.java.ftl
+26
-0
IBZDataAuditMapper.java.ftl
...ava/%SYS_PKGPATH%/util/mapper/IBZDataAuditMapper.java.ftl
+10
-0
IBZDataAuditService.java.ftl
...a/%SYS_PKGPATH%/util/service/IBZDataAuditService.java.ftl
+22
-0
SimpleAuditService.java.ftl
...va/%SYS_PKGPATH%/util/service/SimpleAuditService.java.ftl
+346
-0
未找到文件。
SLN/%PUBPRJ%-core/src/main/java/%SYS_PKGPATH%/core/%MOD_PKGPATH%/domain/%DE%.java.ftl
浏览文件 @
eedfa55f
...
...
@@ -89,6 +89,11 @@ public class ${item.getCodeName()} extends EntityMP implements Serializable {
/**
*
${
defield
.
getLogicName
()}
*/
<#
comment
>
审计注解
</#
comment
>
<#
if
defield
.
isEnableAudit
()==
true
&&
de
.
getAuditMode
()
!=0>
<#
assign
auditExpression
=
getAuditExpression
(
defield
)>
@${
pub
.
getPKGCodeName
()}.
util
.
annotation
.
Audit
(${
auditExpression
})
</#
if
>
<#
comment
>
属性默认值
</#
comment
>
<#
if
defieldano
??
&&
defieldano
!='' && defield.isPhisicalDEField()==true>
@
DEField
(${
defieldano
})
...
...
@@ -336,6 +341,11 @@ public class ${item.getCodeName()} extends EntityMongo implements Serializable {
*/
<#
if
defield
.
isKeyDEField
()==
true
>
@
Id
()
</#
if
>
<#
comment
>
审计注解
</#
comment
>
<#
if
defield
.
isEnableAudit
()==
true
&&
de
.
getAuditMode
()
!=0>
<#
assign
auditExpression
=
getAuditExpression
(
defield
)>
@${
pub
.
getPKGCodeName
()}.
util
.
annotation
.
Audit
(${
auditExpression
})
</#
if
>
<#
comment
>
属性默认值
</#
comment
>
<#
if
defieldano
??
&&
defieldano
!='' && defield.isPhisicalDEField()==true>
...
...
@@ -501,6 +511,11 @@ public class ${item.getCodeName()} extends EntityClient implements Serializable
/**
*
${
defield
.
getLogicName
()}
*/
<#
comment
>
审计注解
</#
comment
>
<#
if
defield
.
isEnableAudit
()==
true
&&
de
.
getAuditMode
()
!=0>
<#
assign
auditExpression
=
getAuditExpression
(
defield
)>
@${
pub
.
getPKGCodeName
()}.
util
.
annotation
.
Audit
(${
auditExpression
})
</#
if
>
<#
comment
>
属性默认值
</#
comment
>
<#
if
defieldano
??
&&
defieldano
!='' && defield.isPhisicalDEField()==true>
@
DEField
(${
defieldano
})
...
...
@@ -677,6 +692,11 @@ public class ${item.getCodeName()} extends EntityBase implements Serializable {
/**
*
${
defield
.
getLogicName
()}
*/
<#
comment
>
审计注解
</#
comment
>
<#
if
defield
.
isEnableAudit
()==
true
&&
de
.
getAuditMode
()
!=0>
<#
assign
auditExpression
=
getAuditExpression
(
defield
)>
@${
pub
.
getPKGCodeName
()}.
util
.
annotation
.
Audit
(${
auditExpression
})
</#
if
>
<#
comment
>
属性默认值
</#
comment
>
<#
if
defieldano
??
&&
defieldano
!='' && defield.isPhisicalDEField()==true>
@
DEField
(${
defieldano
})
...
...
@@ -823,6 +843,28 @@ public class ${item.getCodeName()} extends EntityBase implements Serializable {
<#
return
unionKeyResult
>
</#
function
>
<#
comment
>
审计注解
</#
comment
>
<#
function
getAuditExpression
defield
>
<#
assign
defDataType
=
(
defield
.
getDataType
())
!"">
<#
assign
defStdType
=
srfjavatype
(
defield
.
stdDataType
)>
<#
assign
expressionCond
=
"fieldLogicName=
\"
"
+
defield
.
getLogicName
()+
"
\"
"
>
//
拼接字段逻辑名
<#
if
defield
.
getPSCodeList
??
&&
defield
.
getPSCodeList
()??>
<#
if
((
defield
.
getPredefinedType
())
!'')!='LOGICVALID'>
<#
assign
expressionCond
=
expressionCond
+
",dictName=
\"
"
+
sys
.
codeName
+
"_"
+
defield
.
getPSCodeList
().
codeName
+
"CodeList"
+
"
\"
"
>
//
拼接代码表
</#
if
>
</#
if
>
<#
if
defDataType
==
"DATETIME"
>//
拼接时间
<#
assign
expressionCond
=
expressionCond
+
",fieldType=
\"
DATETIME
\"
,format=
\"
yyyy-MM-dd HH:mm:ss
\"
"
>//
日期时间型
<#
elseif
defDataType
==
"DATE"
>
<#
assign
expressionCond
=
expressionCond
+
",fieldType=
\"
DATE
\"
,format=
\"
yyyy-MM-dd
\"
"
>//
日期型
<#
elseif
defDataType
==
"TIME"
>
<#
assign
expressionCond
=
expressionCond
+
",fieldType=
\"
TIME
\"
,format=
\"
HH:mm
\"
"
>//
时间型
<#
elseif
defDataType
==
'PICKUPDATA'
&&
defStdType
==
'Timestamp'
><#
comment
>
外键值附加数据,数据类型为时间
</#
comment
>
<#
assign
expressionCond
=
expressionCond
+
",fieldType=
\"
DATETIME
\"
,format=
\"
yyyy-MM-dd HH:mm:ss
\"
"
>//
日期时间型
</#
if
>
<#
return
expressionCond
/>
</#
function
>
...
...
SLN/%PUBPRJ%-core/src/main/resources/liquibase/changelog/20200709124030_init_ibzaudit.xml.ftl
0 → 100644
浏览文件 @
eedfa55f
<#ibiztemplate>
TARGET=PSSYSTEM
</#ibiztemplate>
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
<changeSet author="Think (generated)" id="1566027230162-1">
<preConditions onFail="MARK_RAN" >
<not>
<tableExists tableName="IBZDATAAUDIT" />
</not>
</preConditions>
<createTable remarks="数据审计" tableName="IBZDATAAUDIT">
<column name="DATAAUDITID" remarks="数据审计标识" type="VARCHAR2(100 BYTE)">
<constraints primaryKey="true" primaryKeyName="SYS_C00115093"/>
</column>
<column name="OPPERSONID" remarks="操作人标识" type="VARCHAR2(100 BYTE)"/>
<column name="OPPERSONNAME" remarks="操作人名称" type="VARCHAR2(100 BYTE)"/>
<column name="AUDITTYPE" remarks="审计行为类型" type="VARCHAR2(60 BYTE)"/>
<column name="OPTIME" remarks="操作时间" type="date"/>
<column name="IPADDRESS" remarks="访问地址" type="VARCHAR2(100 BYTE)"/>
<column name="AUDITOBJECTDATA" remarks="审计对象(表数据)" type="VARCHAR2(100 BYTE)"/>
<column name="AUDITOBJECT" remarks="审计对象(表)" type="VARCHAR2(100 BYTE)"/>
<column name="AUDITINFO" remarks="审计明细" type="CLOB"/>
<column name="ISDATACHANGED" remarks="审计数据是否发生变化" type="INTEGER"/>
</createTable>
</changeSet>
</databaseChangeLog>
SLN/%PUBPRJ%-util/src/main/java/%SYS_PKGPATH%/util/annotation/Audit.java.ftl
0 → 100644
浏览文件 @
eedfa55f
<#
ibiztemplate
>
TARGET
=
PSSYSTEM
</#
ibiztemplate
>
package
${
pub
.
getPKGCodeName
()}.
util
.
annotation
;
import
java
.
lang
.
annotation
.
ElementType
;
import
java
.
lang
.
annotation
.
Retention
;
import
java
.
lang
.
annotation
.
RetentionPolicy
;
import
java
.
lang
.
annotation
.
Target
;
@
Retention
(
RetentionPolicy
.
RUNTIME
)
@
Target
({
ElementType
.
FIELD
})
public
@
interface
Audit
{
String
fieldLogicName
()
default
""
;//
字段逻辑名称
String
dictName
()
default
""
;//
代码表名称
String
fieldType
()
default
""
;//
字段类型
String
format
()
default
""
;//
格式化
}
SLN/%PUBPRJ%-util/src/main/java/%SYS_PKGPATH%/util/aspect/AuditAspect.java.ftl
0 → 100644
浏览文件 @
eedfa55f
<#
ibiztemplate
>
TARGET
=
PSSYSTEM
</#
ibiztemplate
>
package
${
pub
.
getPKGCodeName
()}.
util
.
aspect
;
import
lombok
.
SneakyThrows
;
import
${
pub
.
getPKGCodeName
()}.
util
.
annotation
.
Audit
;
import
${
pub
.
getPKGCodeName
()}.
util
.
domain
.
EntityBase
;
import
${
pub
.
getPKGCodeName
()}.
util
.
helper
.
DEFieldCacheMap
;
import
${
pub
.
getPKGCodeName
()}.
util
.
service
.
IBZDataAuditService
;
import
org
.
aspectj
.
lang
.
JoinPoint
;
import
org
.
aspectj
.
lang
.
ProceedingJoinPoint
;
import
org
.
aspectj
.
lang
.
annotation
.
AfterReturning
;
import
org
.
aspectj
.
lang
.
annotation
.
Around
;
import
org
.
aspectj
.
lang
.
annotation
.
Aspect
;
import
org
.
springframework
.
beans
.
factory
.
annotation
.
Autowired
;
import
org
.
springframework
.
expression
.
EvaluationContext
;
import
org
.
springframework
.
expression
.
Expression
;
import
org
.
springframework
.
expression
.
ExpressionParser
;
import
org
.
springframework
.
expression
.
spel
.
standard
.
SpelExpressionParser
;
import
org
.
springframework
.
expression
.
spel
.
support
.
StandardEvaluationContext
;
import
org
.
springframework
.
stereotype
.
Component
;
import
org
.
springframework
.
util
.
ObjectUtils
;
import
org
.
springframework
.
util
.
StringUtils
;
import
org
.
springframework
.
web
.
context
.
request
.
RequestAttributes
;
import
org
.
springframework
.
web
.
context
.
request
.
RequestContextHolder
;
import
org
.
springframework
.
web
.
context
.
request
.
ServletRequestAttributes
;
import
javax
.
servlet
.
http
.
HttpServletRequest
;
import
java
.
util
.
Map
;
/**
*
实体数据审计切面类
*/
@
Aspect
@
Component
public
class
AuditAspect
{
private
final
ExpressionParser
parser
=
new
SpelExpressionParser
();
@
Autowired
IBZDataAuditService
dataAuditService
;
/**
*
实体数据建立切面,在成功创建数据后将新增数据内容记录审计日志内(审计明细【
AuditInfo
】中只记录审计属性变化情况,审计属性在平台属性中配置)
*
@
param
point
*/
@
AfterReturning
(
value
=
"execution(* ${pub.getPKGCodeName()}.core.*.service.*.create(..))"
)
@
SneakyThrows
public
void
create
(
JoinPoint
point
){
HttpServletRequest
request
=
null
;
RequestAttributes
requestAttributes
=
RequestContextHolder
.
getRequestAttributes
();
if
(
requestAttributes
!=null){
request
=((
ServletRequestAttributes
)
requestAttributes
).
getRequest
();
}
Object
[]
args
=
point
.
getArgs
();
if
(
ObjectUtils
.
isEmpty
(
args
)
||
args
.
length
==
0
)
return
;
Object
serviceParam
=
args
[
0
];
EntityBase
entity
=(
EntityBase
)
serviceParam
;//
创建数据
Map
<
String
,
Audit
>
auditFields
=
DEFieldCacheMap
.
getAuditFields
(
entity
.
getClass
());
if
(
auditFields
.
size
()==
0
)//
是否有审计属性
return
;
String
idField
=
DEFieldCacheMap
.
getDEKeyField
(
entity
.
getClass
());
Object
idValue
=
""
;
if
(
!StringUtils.isEmpty(idField)){
idValue
=
entity
.
get
(
idField
);
}
//
记录审计日志
dataAuditService
.
createAudit
(
request
,
entity
,
idValue
,
auditFields
);
return
;
}
/**
*
实体数据更新切面,在成功更新数据后将新增数据内容记录审计日志内(审计明细【
AuditInfo
】中只记录审计属性变化情况,审计属性在平台属性中配置)
*
使用环切【
@
Around
】获取到更新前后的实体数据并进行差异比较,并将差异内容记入审计日志内
*
@
param
point
*/
@
Around
(
"execution(* ${pub.getPKGCodeName()}.core.*.service.*.update(..))"
)
public
Object
update
(
ProceedingJoinPoint
point
)
throws
Throwable
{
HttpServletRequest
request
=
null
;
RequestAttributes
requestAttributes
=
RequestContextHolder
.
getRequestAttributes
();
if
(
requestAttributes
!=null){
request
=((
ServletRequestAttributes
)
requestAttributes
).
getRequest
();
}
Object
serviceObj
=
point
.
getTarget
();
Object
args
[]=
point
.
getArgs
();
if
(
ObjectUtils
.
isEmpty
(
args
)
||
args
.
length
==
0
)
return
point
.
proceed
();
Object
arg
=
args
[
0
];
EntityBase
entity
=
(
EntityBase
)
arg
;
Map
<
String
,
Audit
>
auditFields
=
DEFieldCacheMap
.
getAuditFields
(
entity
.
getClass
());
//
是否有审计属性
if
(
auditFields
.
size
()==
0
)
return
point
.
proceed
();
String
idField
=
DEFieldCacheMap
.
getDEKeyField
(
entity
.
getClass
());
Object
idValue
=
""
;
if
(
!StringUtils.isEmpty(idField)){
idValue
=
entity
.
get
(
idField
);
}
if
(
ObjectUtils
.
isEmpty
(
idValue
))
return
point
.
proceed
();
//
获取更新前实体
EntityBase
beforeEntity
=
getEntity
(
serviceObj
,
idValue
);
//
执行更新操作
point
.
proceed
();
//
记录审计日志
dataAuditService
.
updateAudit
(
request
,
beforeEntity
,
serviceObj
,
idValue
,
auditFields
);
return
true
;
}
/**
*
实体数据更新切面,在成功更新数据后将新增数据内容记录审计日志内(审计明细【
AuditInfo
】中只记录审计属性变化情况,审计属性在平台属性中配置)
*
使用环切【
@
Around
】获取要删除的完整数据,并将审计属性相关信息记录到审计日志中
*
@
param
point
*
@
return
*
@
throws
Throwable
*/
@
Around
(
"execution(* ${pub.getPKGCodeName()}.core.*.service.*.remove(..))"
)
public
Object
remove
(
ProceedingJoinPoint
point
)
throws
Throwable
{
HttpServletRequest
request
=
null
;
RequestAttributes
requestAttributes
=
RequestContextHolder
.
getRequestAttributes
();
if
(
requestAttributes
!=null){
request
=((
ServletRequestAttributes
)
requestAttributes
).
getRequest
();
}
Object
serviceObj
=
point
.
getTarget
();
Object
args
[]=
point
.
getArgs
();
if
(
ObjectUtils
.
isEmpty
(
args
)
||
args
.
length
==
0
)
return
point
.
proceed
();
Object
idValue
=
args
[
0
];
EntityBase
entity
=
getEntity
(
serviceObj
,
idValue
);
Map
<
String
,
Audit
>
auditFields
=
DEFieldCacheMap
.
getAuditFields
(
entity
.
getClass
());
if
(
auditFields
.
size
()==
0
){
return
point
.
proceed
();
}
else
{
//
执行删除操作
point
.
proceed
();
//
记录审计日志
dataAuditService
.
removeAudit
(
request
,
entity
,
idValue
,
auditFields
);
return
true
;
}
}
/**
*
获取实体
*
@
param
service
*
@
param
id
*
@
return
*/
@
SneakyThrows
private
EntityBase
getEntity
(
Object
service
,
Object
id
){
EntityBase
entity
=
null
;
if
(
!ObjectUtils.isEmpty(service)){
EvaluationContext
oldContext
=
new
StandardEvaluationContext
();
oldContext
.
setVariable
(
"service"
,
service
);
oldContext
.
setVariable
(
"id"
,
id
);
Expression
oldExp
=
parser
.
parseExpression
(
"#service.get(#id)"
);
return
oldExp
.
getValue
(
oldContext
,
EntityBase
.
class
);
}
return
entity
;
}
}
\ No newline at end of file
SLN/%PUBPRJ%-util/src/main/java/%SYS_PKGPATH%/util/domain/IBZDataAudit.java.ftl
0 → 100644
浏览文件 @
eedfa55f
<#
ibiztemplate
>
TARGET
=
PSSYSTEM
</#
ibiztemplate
>
package
${
pub
.
getPKGCodeName
()}.
util
.
domain
;
import
com
.
baomidou
.
mybatisplus
.
annotation
.
IdType
;
import
com
.
baomidou
.
mybatisplus
.
annotation
.
TableId
;
import
com
.
baomidou
.
mybatisplus
.
annotation
.
TableName
;
import
com
.
fasterxml
.
jackson
.
annotation
.
JsonIgnoreProperties
;
import
lombok
.
Data
;
import
java
.
io
.
Serializable
;
import
java
.
sql
.
Timestamp
;
import
java
.
util
.
Objects
;
/**
*
实体
[
DataAudit
]
数据对象
*/
@
TableName
(
value
=
"IBZDATAAUDIT"
)
@
JsonIgnoreProperties
(
ignoreUnknown
=
true
)
@
Data
public
class
IBZDataAudit
implements
Serializable
{
@
TableId
(
value
=
"dataauditid"
,
type
=
IdType
.
UUID
)//
指定主键生成策略
private
String
dataauditid
;
private
String
dataauditname
;
private
String
oppersonid
;
private
String
oppersonname
;
private
String
audittype
;
private
Timestamp
optime
;
private
String
ipaddress
;
private
String
auditinfo
;
private
Object
auditobjectdata
;
private
String
auditobject
;
private
int
isdatachanged
;
}
\ No newline at end of file
SLN/%PUBPRJ%-util/src/main/java/%SYS_PKGPATH%/util/helper/DEFieldCacheMap.java.ftl
浏览文件 @
eedfa55f
...
...
@@ -4,6 +4,7 @@ TARGET=PSSYSTEM
package
${
pub
.
getPKGCodeName
()}.
util
.
helper
;
import
${
pub
.
getPKGCodeName
()}.
util
.
annotation
.
Audit
;
import
${
pub
.
getPKGCodeName
()}.
util
.
annotation
.
DEField
;
import
org
.
springframework
.
util
.
ObjectUtils
;
import
org
.
springframework
.
util
.
StringUtils
;
...
...
@@ -25,6 +26,8 @@ public class DEFieldCacheMap {
private
static
Hashtable
<
String
,
Hashtable
<
String
,
DEField
>>
cacheDEField
=
new
Hashtable
<>();
private
static
Hashtable
<
String
,
Hashtable
<
String
,
Audit
>>
cacheAuditField
=
new
Hashtable
<>();
private
static
Hashtable
<
String
,
String
>
cacheDEKeyField
=
new
Hashtable
<>();
private
static
Object
objLock1
=
new
Object
();
...
...
@@ -47,6 +50,7 @@ public class DEFieldCacheMap {
List
<
Field
>
list
=
new
ArrayList
<
Field
>();
Hashtable
<
String
,
String
>
keys
=
new
Hashtable
<
String
,
String
>();
Hashtable
<
String
,
DEField
>
defields
=
new
Hashtable
<>();
Hashtable
<
String
,
Audit
>
auditfields
=
new
Hashtable
<>();
Hashtable
<
String
,
String
>
dekeyfields
=
new
Hashtable
<>();
Field
[]
fields
=
clazz
.
getDeclaredFields
();
for
(
Field
field
:
fields
){
...
...
@@ -54,16 +58,21 @@ public class DEFieldCacheMap {
list
.
add
(
field
);
keys
.
put
(
field
.
getName
().
toLowerCase
(),
field
.
getName
());
DEField
deField
=
field
.
getAnnotation
(
DEField
.
class
);
Audit
auditField
=
field
.
getAnnotation
(
Audit
.
class
);
if
(
!ObjectUtils.isEmpty(deField)) {
defields
.
put
(
field
.
getName
(),
deField
);
if
(
deField
.
isKeyField
())
cacheDEKeyField
.
put
(
className
,
field
.
getName
());
}
if
(
!ObjectUtils.isEmpty(auditField)) {
auditfields
.
put
(
field
.
getName
(),
auditField
);
}
}
cacheMap
.
put
(
className
,
result
);
cacheList
.
put
(
className
,
list
);
cacheKey
.
put
(
className
,
keys
);
cacheDEField
.
put
(
className
,
defields
);
cacheAuditField
.
put
(
className
,
auditfields
);
return
result
;
}
}
...
...
@@ -100,6 +109,23 @@ public class DEFieldCacheMap {
}
}
/**
*
从缓存中查询审计属性集合
*
@
param
*
@
return
*/
public
static
<
T
>
Hashtable
<
String
,
Audit
>
getAuditFields
(
Class
<
T
>
clazz
)
{
String
className
=
clazz
.
getName
();
if
(
className
.
indexOf
(
"_$"
)>
0
)
className
=
className
.
substring
(
0
,
className
.
lastIndexOf
(
"_$"
));
if
(
cacheAuditField
.
containsKey
(
className
))
return
cacheAuditField
.
get
(
className
);
else
{
DEFieldCacheMap
.
getFieldMap
(
className
);
return
cacheAuditField
.
get
(
className
);
}
}
/**
*
从缓存中查询实体对象主键
*
@
param
...
...
SLN/%PUBPRJ%-util/src/main/java/%SYS_PKGPATH%/util/mapper/IBZDataAuditMapper.java.ftl
0 → 100644
浏览文件 @
eedfa55f
<#
ibiztemplate
>
TARGET
=
PSSYSTEM
</#
ibiztemplate
>
package
${
pub
.
getPKGCodeName
()}.
util
.
mapper
;
import
com
.
baomidou
.
mybatisplus
.
core
.
mapper
.
BaseMapper
;
import
${
pub
.
getPKGCodeName
()}.
util
.
domain
.
IBZDataAudit
;
public
interface
IBZDataAuditMapper
extends
BaseMapper
<
IBZDataAudit
>
{
}
\ No newline at end of file
SLN/%PUBPRJ%-util/src/main/java/%SYS_PKGPATH%/util/service/IBZDataAuditService.java.ftl
0 → 100644
浏览文件 @
eedfa55f
<#
ibiztemplate
>
TARGET
=
PSSYSTEM
</#
ibiztemplate
>
package
${
pub
.
getPKGCodeName
()}.
util
.
service
;
import
${
pub
.
getPKGCodeName
()}.
util
.
annotation
.
Audit
;
import
${
pub
.
getPKGCodeName
()}.
util
.
domain
.
EntityBase
;
import
org
.
springframework
.
scheduling
.
annotation
.
Async
;
import
javax
.
servlet
.
http
.
HttpServletRequest
;
import
java
.
util
.
Map
;
/**
*
实体
[
DataAudit
]
服务对象接口
*/
public
interface
IBZDataAuditService
{
@
Async
void
createAudit
(
HttpServletRequest
request
,
EntityBase
entity
,
Object
idValue
,
Map
<
String
,
Audit
>
auditFields
);
@
Async
void
updateAudit
(
HttpServletRequest
request
,
EntityBase
beforeEntity
,
Object
serviceObj
,
Object
idValue
,
Map
<
String
,
Audit
>
auditFields
);
@
Async
void
removeAudit
(
HttpServletRequest
request
,
EntityBase
entity
,
Object
idValue
,
Map
<
String
,
Audit
>
auditFields
);
}
\ No newline at end of file
SLN/%PUBPRJ%-util/src/main/java/%SYS_PKGPATH%/util/service/SimpleAuditService.java.ftl
0 → 100644
浏览文件 @
eedfa55f
<#
ibiztemplate
>
TARGET
=
PSSYSTEM
</#
ibiztemplate
>
package
${
pub
.
getPKGCodeName
()}.
util
.
service
;
import
com
.
alibaba
.
fastjson
.
JSONArray
;
import
com
.
alibaba
.
fastjson
.
JSONObject
;
import
com
.
baomidou
.
mybatisplus
.
extension
.
service
.
impl
.
ServiceImpl
;
import
lombok
.
SneakyThrows
;
import
lombok
.
extern
.
slf4j
.
Slf4j
;
import
${
pub
.
getPKGCodeName
()}.
util
.
annotation
.
Audit
;
import
${
pub
.
getPKGCodeName
()}.
util
.
domain
.
EntityBase
;
import
${
pub
.
getPKGCodeName
()}.
util
.
domain
.
IBZDataAudit
;
import
${
pub
.
getPKGCodeName
()}.
util
.
mapper
.
IBZDataAuditMapper
;
import
${
pub
.
getPKGCodeName
()}.
util
.
security
.
AuthenticationUser
;
import
org
.
springframework
.
expression
.
EvaluationContext
;
import
org
.
springframework
.
expression
.
Expression
;
import
org
.
springframework
.
expression
.
ExpressionParser
;
import
org
.
springframework
.
expression
.
spel
.
standard
.
SpelExpressionParser
;
import
org
.
springframework
.
expression
.
spel
.
support
.
StandardEvaluationContext
;
import
org
.
springframework
.
scheduling
.
annotation
.
Scheduled
;
import
org
.
springframework
.
stereotype
.
Service
;
import
org
.
springframework
.
util
.
ObjectUtils
;
import
org
.
springframework
.
util
.
StringUtils
;
import
javax
.
servlet
.
http
.
HttpServletRequest
;
import
java
.
sql
.
Timestamp
;
import
java
.
text
.
SimpleDateFormat
;
import
java
.
util
.*;
/**
*
实体
[
DataAudit
]
服务对象接口实现
*/
@
Service
@
Slf4j
public
class
SimpleAuditService
extends
ServiceImpl
<
IBZDataAuditMapper
,
IBZDataAudit
>
implements
IBZDataAuditService
{
private
final
ExpressionParser
parser
=
new
SpelExpressionParser
();
private
static
List
cacheMap
=
Collections
.
synchronizedList
(
new
ArrayList
());
@
Override
public
boolean
save
(
IBZDataAudit
entity
)
{
cacheMap
.
add
(
entity
);
log
.
info
(
String
.
format
(
"当前待保存审计集合数量为[%S]"
,
cacheMap
.
size
()));
return
false
;
}
@
Scheduled
(
fixedRate
=
10000
)
public
void
saveAudit
()
{
if
(
cacheMap
.
size
()>
0
){
log
.
info
(
String
.
format
(
"正在保存审计数据,当前审计集合数量为[%S]"
,
cacheMap
.
size
()));
List
temp
=
new
ArrayList
();
if
(
cacheMap
.
size
()<
2
)
temp
.
addAll
(
cacheMap
);
else
temp
.
addAll
(
cacheMap
.
subList
(
0
,
2
));
this
.
saveBatch
(
temp
);
cacheMap
.
removeAll
(
temp
);
log
.
info
(
String
.
format
(
"保存完成,当前审计集合数量为[%S]"
,
cacheMap
.
size
()));
}
}
/**
*
新建审计日志
*
@
param
request
*
@
param
entity
*
@
param
idValue
*
@
param
auditFields
*/
@
Override
public
void
createAudit
(
HttpServletRequest
request
,
EntityBase
entity
,
Object
idValue
,
Map
<
String
,
Audit
>
auditFields
)
{
IBZDataAudit
dataAudit
=
new
IBZDataAudit
();
dataAudit
.
setOppersonid
(
AuthenticationUser
.
getAuthenticationUser
().
getUserid
());
dataAudit
.
setOppersonname
(
String
.
format
(
"%s[%s]"
,
AuthenticationUser
.
getAuthenticationUser
().
getPersonname
(),
AuthenticationUser
.
getAuthenticationUser
().
getOrgname
()));
dataAudit
.
setAudittype
(
"CREATE"
);
dataAudit
.
setAuditobject
(
entity
.
getClass
().
getSimpleName
());
dataAudit
.
setAuditobjectdata
(
idValue
);
dataAudit
.
setOptime
(
new
Timestamp
(
new
Date
().
getTime
()));
if
(
request
!=null)
dataAudit
.
setIpaddress
(
getIpAddress
(
request
,
AuthenticationUser
.
getAuthenticationUser
()));
dataAudit
.
setAuditinfo
(
getCreateAuditInfo
(
entity
,
auditFields
));
dataAudit
.
setIsdatachanged
(
1
);
save
(
dataAudit
);
}
/**
*
更新审计日志
*
@
param
request
*
@
param
beforeEntity
*
@
param
serviceObj
*
@
param
idValue
*
@
param
auditFields
*/
@
SneakyThrows
public
void
updateAudit
(
HttpServletRequest
request
,
EntityBase
beforeEntity
,
Object
serviceObj
,
Object
idValue
,
Map
<
String
,
Audit
>
auditFields
){
System
.
out
.
println
(
"updateAudit--开始休眠"
);
Thread
.
sleep
(
10000
);
//
获取更新后的实体
EntityBase
afterEntity
=
getEntity
(
serviceObj
,
idValue
);
//
获取更新后的审计内容
String
auditInfo
=
getUpdateAuditInfo
(
beforeEntity
,
afterEntity
,
auditFields
);//
比较更新前后差异内容
int
isDataChanged
=
1
;
if
(
StringUtils
.
isEmpty
(
auditInfo
))//
审计内容是否发生变化
isDataChanged
=
0
;
IBZDataAudit
dataAudit
=
new
IBZDataAudit
();
dataAudit
.
setOppersonid
(
AuthenticationUser
.
getAuthenticationUser
().
getUserid
());
dataAudit
.
setOppersonname
(
String
.
format
(
"%s[%s]"
,
AuthenticationUser
.
getAuthenticationUser
().
getPersonname
(),
AuthenticationUser
.
getAuthenticationUser
().
getOrgname
()));
dataAudit
.
setAudittype
(
"UPDATE"
);
dataAudit
.
setAuditobject
(
afterEntity
.
getClass
().
getSimpleName
());
dataAudit
.
setAuditobjectdata
(
idValue
);
dataAudit
.
setOptime
(
new
Timestamp
(
new
Date
().
getTime
()));
if
(
request
!=null)
dataAudit
.
setIpaddress
(
getIpAddress
(
request
,
AuthenticationUser
.
getAuthenticationUser
()));
dataAudit
.
setAuditinfo
(
auditInfo
);
dataAudit
.
setIsdatachanged
(
isDataChanged
);
save
(
dataAudit
);
System
.
out
.
println
(
"updateAudit--结束休眠"
);
}
/**
*
删除审计日志
*
@
param
request
*
@
param
entity
*
@
param
idValue
*
@
param
auditFields
*/
public
void
removeAudit
(
HttpServletRequest
request
,
EntityBase
entity
,
Object
idValue
,
Map
<
String
,
Audit
>
auditFields
){
IBZDataAudit
dataAudit
=
new
IBZDataAudit
();
dataAudit
.
setOppersonid
(
AuthenticationUser
.
getAuthenticationUser
().
getUserid
());
dataAudit
.
setOppersonname
(
String
.
format
(
"%s[%s]"
,
AuthenticationUser
.
getAuthenticationUser
().
getPersonname
(),
AuthenticationUser
.
getAuthenticationUser
().
getOrgname
()));
dataAudit
.
setAudittype
(
"REMOVE"
);
dataAudit
.
setAuditobject
(
entity
.
getClass
().
getSimpleName
());
dataAudit
.
setAuditobjectdata
(
idValue
);
dataAudit
.
setOptime
(
new
Timestamp
(
new
Date
().
getTime
()));
if
(
request
!=null)
dataAudit
.
setIpaddress
(
getIpAddress
(
request
,
AuthenticationUser
.
getAuthenticationUser
()));
dataAudit
.
setAuditinfo
(
getRemoveAuditInfo
(
entity
,
auditFields
));
dataAudit
.
setIsdatachanged
(
1
);
save
(
dataAudit
);
}
/**
*
获取新建审计内容
*
@
param
entity
*
@
param
auditFields
*
@
return
*/
private
String
getCreateAuditInfo
(
EntityBase
entity
,
Map
<
String
,
Audit
>
auditFields
){
JSONArray
auditFieldArray
=
new
JSONArray
();
String
auditResult
=
""
;
if
(
auditFields
.
size
()==
0
)
return
""
;
for
(
Map
.
Entry
<
String
,
Audit
>
auditField
:
auditFields
.
entrySet
())
{
Object
objFieldName
=
auditField
.
getKey
();//
获取注解字段
Audit
auditAnnotation
=
auditField
.
getValue
();//
拿到注解
String
fieldLogicName
=
auditAnnotation
.
fieldLogicName
();
String
fieldName
=
String
.
valueOf
(
objFieldName
);
//
属性名称
Object
value
=
entity
.
get
(
fieldName
);//
老属性值
value
=
dataTransfer
(
value
,
auditAnnotation
.
fieldType
(),
auditAnnotation
.
format
());//
属性值转换
if
(
!StringUtils.isEmpty(value)){
JSONObject
auditFieldObj
=
new
JSONObject
();
auditFieldObj
.
put
(
"field"
,
fieldLogicName
);
auditFieldObj
.
put
(
"value"
,
value
);
if
(
!StringUtils.isEmpty(auditAnnotation.dictName())){
auditFieldObj
.
put
(
"dictName"
,
auditAnnotation
.
dictName
());
}
auditFieldArray
.
add
(
auditFieldObj
);
}
}
if
(
auditFieldArray
.
size
()>
0
){
auditResult
=
auditFieldArray
.
toString
();
}
return
auditResult
;
}
/**
*
获取更新审计内容
*
@
param
oldData
*
@
param
newData
*
@
param
auditFields
*
@
return
*/
private
String
getUpdateAuditInfo
(
EntityBase
oldData
,
EntityBase
newData
,
Map
<
String
,
Audit
>
auditFields
){
String
auditResult
=
""
;
JSONArray
auditFieldArray
=
new
JSONArray
();
if
(
auditFields
.
size
()==
0
)
return
auditResult
;
for
(
Map
.
Entry
<
String
,
Audit
>
auditField
:
auditFields
.
entrySet
())
{
Object
objFieldName
=
auditField
.
getKey
();//
获取注解字段
String
fieldName
=
String
.
valueOf
(
objFieldName
);
//
属性名称
Audit
auditAnnotation
=
auditField
.
getValue
();//
拿到注解
String
fieldLogicName
=
auditAnnotation
.
fieldLogicName
();//
获取字段逻辑名称
Object
oldValue
=
oldData
.
get
(
fieldName
);//
老属性值
Object
newValue
=
newData
.
get
(
fieldName
);//
新属性值
if
(
!compare(oldValue,newValue)){
oldValue
=
dataTransfer
(
oldValue
,
auditAnnotation
.
fieldType
(),
auditAnnotation
.
format
());//
属性值转换
newValue
=
dataTransfer
(
newValue
,
auditAnnotation
.
fieldType
(),
auditAnnotation
.
format
());//
属性值转换
JSONObject
auditFieldObj
=
new
JSONObject
();
auditFieldObj
.
put
(
"field"
,
fieldLogicName
);
auditFieldObj
.
put
(
"source"
,
oldValue
);
auditFieldObj
.
put
(
"target"
,
newValue
);
if
(
!StringUtils.isEmpty(auditAnnotation.dictName())){
auditFieldObj
.
put
(
"dictName"
,
auditAnnotation
.
dictName
());
}
auditFieldArray
.
add
(
auditFieldObj
);
}
}
if
(
auditFieldArray
.
size
()>
0
){
auditResult
=
auditFieldArray
.
toString
();
}
return
auditResult
;
}
/**
*
获取删除审计内容
*
@
param
entity
*
@
param
auditFields
*
@
return
*/
private
String
getRemoveAuditInfo
(
EntityBase
entity
,
Map
<
String
,
Audit
>
auditFields
){
String
auditResult
=
""
;
JSONArray
auditFieldArray
=
new
JSONArray
();
if
(
auditFields
.
size
()==
0
)
return
auditResult
;
for
(
Map
.
Entry
<
String
,
Audit
>
auditField
:
auditFields
.
entrySet
())
{
Object
objFieldName
=
auditField
.
getKey
();//
获取注解字段
Audit
auditAnnotation
=
auditField
.
getValue
();//
拿到注解
String
fieldLogicName
=
auditAnnotation
.
fieldLogicName
();
String
fieldName
=
String
.
valueOf
(
objFieldName
);
//
属性名称
Object
value
=
entity
.
get
(
fieldName
);//
老属性值
value
=
dataTransfer
(
value
,
auditAnnotation
.
fieldType
(),
auditAnnotation
.
format
());//
属性值转换
if
(
!StringUtils.isEmpty(value)){
JSONObject
auditFieldObj
=
new
JSONObject
();
auditFieldObj
.
put
(
"field"
,
fieldLogicName
);
auditFieldObj
.
put
(
"value"
,
value
);
if
(
!StringUtils.isEmpty(auditAnnotation.dictName())){
auditFieldObj
.
put
(
"dictName"
,
auditAnnotation
.
dictName
());
}
auditFieldArray
.
add
(
auditFieldObj
);
}
}
if
(
auditFieldArray
.
size
()>
0
){
auditResult
=
auditFieldArray
.
toString
();
}
return
auditResult
;
}
/**
*
数据转换
*
@
param
value
转换值
*
@
param
dataType
转换字段类型
*
@
param
strFormat
转换字段格式化文本
*
@
return
*/
private
String
dataTransfer
(
Object
value
,
String
dataType
,
String
strFormat
){
if
(
value
==
null
)
return
""
;
String
transResult
=
value
.
toString
();
if
((
dataType
.
equals
(
"DATE"
)
||
dataType
.
equals
(
"DATETIME"
)
||
dataType
.
equals
(
"TIME"
))
&&
(
!StringUtils.isEmpty(strFormat))){ //时间类型转换
Timestamp
timestamp
=(
Timestamp
)
value
;
Date
date
=
timestamp
;
SimpleDateFormat
format
=
new
SimpleDateFormat
(
strFormat
);
transResult
=
format
.
format
(
date
);
}
return
transResult
;
}
/**
*
对象比较
*
@
param
sourceObj
比较源对象
*
@
param
targetObj
比较目标对象
*
@
return
*/
private
boolean
compare
(
Object
sourceObj
,
Object
targetObj
){
if
(
sourceObj
==
null
&&
targetObj
==
null
)
return
true
;
if
(
sourceObj
==
null
&&
targetObj
!=null)
return
false
;
return
sourceObj
.
equals
(
targetObj
);
}
/**
*
获取实体
*
@
param
service
*
@
param
id
*
@
return
*/
@
SneakyThrows
private
EntityBase
getEntity
(
Object
service
,
Object
id
){
EntityBase
entity
=
null
;
if
(
!ObjectUtils.isEmpty(service)){
EvaluationContext
oldContext
=
new
StandardEvaluationContext
();
oldContext
.
setVariable
(
"service"
,
service
);
oldContext
.
setVariable
(
"id"
,
id
);
Expression
oldExp
=
parser
.
parseExpression
(
"#service.get(#id)"
);
return
oldExp
.
getValue
(
oldContext
,
EntityBase
.
class
);
}
return
entity
;
}
/**
*
获取
Ip
地址
*
@
param
request
*
@
return
*/
public
String
getIpAddress
(
HttpServletRequest
request
,
AuthenticationUser
authenticationUser
)
{
//
客户端有提交
ip
,以提交的
ip
为准
if
(
authenticationUser
!= null && !StringUtils.isEmpty(authenticationUser.getAddr())){
return
authenticationUser
.
getAddr
();
}
if
(
request
==
null
)
return
""
;
String
Xip
=
request
.
getHeader
(
"X-Real-IP"
);
String
XFor
=
request
.
getHeader
(
"X-Forwarded-For"
);
if
(
!StringUtils.isEmpty(XFor) && !"unKnown".equalsIgnoreCase(XFor)){
//
多次反向代理后会有多个
ip
值,第一个
ip
才是真实
ip
int
index
=
XFor
.
indexOf
(
","
);
if
(
index
!= -1){
return
XFor
.
substring
(
0
,
index
);
}
else
{
return
XFor
;
}
}
XFor
=
Xip
;
if
(
!StringUtils.isEmpty(XFor) && !"unKnown".equalsIgnoreCase(XFor)){
return
XFor
;
}
if
(
StringUtils
.
isEmpty
(
XFor
)
||
"unknown"
.
equalsIgnoreCase
(
XFor
))
{
XFor
=
request
.
getHeader
(
"Proxy-Client-IP"
);
}
if
(
StringUtils
.
isEmpty
(
XFor
)
||
"unknown"
.
equalsIgnoreCase
(
XFor
))
{
XFor
=
request
.
getHeader
(
"WL-Proxy-Client-IP"
);
}
if
(
StringUtils
.
isEmpty
(
XFor
)
||
"unknown"
.
equalsIgnoreCase
(
XFor
))
{
XFor
=
request
.
getHeader
(
"HTTP_CLIENT_IP"
);
}
if
(
StringUtils
.
isEmpty
(
XFor
)
||
"unknown"
.
equalsIgnoreCase
(
XFor
))
{
XFor
=
request
.
getHeader
(
"HTTP_X_FORWARDED_FOR"
);
}
if
(
StringUtils
.
isEmpty
(
XFor
)
||
"unknown"
.
equalsIgnoreCase
(
XFor
))
{
XFor
=
request
.
getRemoteAddr
();
}
return
XFor
;
}
}
\ No newline at end of file
编辑
预览
Markdown
格式
0%
请重试
or
添加新附件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
先完成此消息的编辑!
取消
想要评论请
注册
或
登录