spring aop mybatis puls 审计日志数据操作前操作后对比记录
Posted wb54979
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring aop mybatis puls 审计日志数据操作前操作后对比记录相关的知识,希望对你有一定的参考价值。
源码下载地址 拖到最下面:
本文主要介绍如何使用mybatis插件实现拦截数据库操作并根据不同需求进行数据对比分析,主要适用于系统中需要对数据操作进行记录、在更新数据时准确记录更新字段
核心:mybatis插件(拦截器)、mybatis-Plus实体规范、数据对比
mybatis插件:
mybatis插件实际上就是官方针对4层数据操作处理预留的拦截器,使用者可以根据不同的需求进行操作拦截并处理。这边笔者不做详细描述,详细介绍请到官网了解。这里不讲述背景,技术,只以代码的形式简单的阐述整个实现过程。
整个实现方式通过mybatis的拦截器+spring aop
maven仓库,省略其它仓库只贴mybatis plus
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>
拦截器实现
import com.baomidou.mybatisplus.core.toolkit.*;
import com.baomidou.mybatisplus.extension.handlers.AbstractSqlParserHandler;
import com.es.user.domain.aspect.DataOperateLogAspect;
import com.es.user.domain.threadlocah.DataOperateLogThreadLocal;
import com.es.user.util.log.OperationDataChange;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import java.lang.reflect.Proxy;
import java.sql.Statement;
import java.util.*;
/**
* <p>
* 数据更新拦截器
* </p>
*
*/
@Component
@Intercepts(@Signature(type = StatementHandler.class, method = "update", args = Statement.class))
public class DataOperateInterceptor extends AbstractSqlParserHandler implements Interceptor
private Logger logger = LoggerFactory.getLogger(DataOperateLogAspect.class);
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public Object intercept(Invocation invocation) throws Exception
// 判断是否需要记录日志
if (DataOperateLogThreadLocal.DATA_CHANGES.get() == null)
return invocation.proceed();
Statement statement;
Object firstArg = invocation.getArgs()[0];
if (Proxy.isProxyClass(firstArg.getClass()))
statement = (Statement) SystemMetaObject.forObject(firstArg).getValue("h.statement");
else
statement = (Statement) firstArg;
MetaObject stmtMetaObj = SystemMetaObject.forObject(statement);
try
statement = (Statement) stmtMetaObj.getValue("stmt.statement");
catch (Exception e)
if (stmtMetaObj.hasGetter("delegate"))
try
statement = (Statement) stmtMetaObj.getValue("delegate");
catch (Exception ignored)
String originalSql = statement.toString();
originalSql = originalSql.replaceAll("[\\\\s]+", StringPool.SPACE);
int index = indexOfSqlStart(originalSql);
if (index > 0)
originalSql = originalSql.substring(index);
StatementHandler statementHandler = PluginUtils.realTarget(invocation.getTarget());
MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
this.sqlParser(metaObject);
MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
if(mappedStatement.getSqlCommandType() != null)
try
// 获取执行Sql
String sql = originalSql.replace("where", "WHERE");
// 使用mybatis-plus 工具解析sql获取表名
Collection<String> tables = new TableNameParser(sql).tables();
if (CollectionUtils.isEmpty(tables))
return invocation.proceed();
String tableName = tables.iterator().next();
//更新数据
if (SqlCommandType.UPDATE.equals(mappedStatement.getSqlCommandType()))
OperationDataChange change = new OperationDataChange();
change.setTableName(tableName);
change.setJdbcTemplate(jdbcTemplate);
// 设置sql用于执行完后查询新数据
String selectSql = sql.substring(sql.lastIndexOf("WHERE") + 5);
// 同表对同条数据操作多次只进行一次对比
if (DataOperateLogThreadLocal.DATA_CHANGES.get().stream().anyMatch(c -> tableName.equals(c.getTableName())
&& selectSql.equals(c.getWhereSql())))
return invocation.proceed();
change.setWhereSql(selectSql);
// 获取请求时object
Object parameterObject = statementHandler.getParameterHandler().getParameterObject();
change.setTransferData(Arrays.asList(parameterObject));
String querySql = "select * from "+tableName+" where "+selectSql;
change.setQuerySql(querySql);
List<Map<String, Object>> maps = jdbcTemplate.queryForList(querySql);
//Object obj = JSONObject.parseObject(JSON.toJSONString(maps.get(0)),parameterObject.getClass());
change.setOldData(maps);
change.setEntityType(parameterObject.getClass());
DataOperateLogThreadLocal.DATA_CHANGES.get().add(change);
catch (Exception e)
return invocation.proceed();
/**
* 获取sql语句开头部分
*
* @param sql ignore
* @return ignore
*/
private int indexOfSqlStart(String sql)
String upperCaseSql = sql.toUpperCase();
Set<Integer> set = new HashSet<>();
set.add(upperCaseSql.indexOf("SELECT "));
set.add(upperCaseSql.indexOf("UPDATE "));
set.add(upperCaseSql.indexOf("INSERT "));
set.add(upperCaseSql.indexOf("DELETE "));
set.remove(-1);
if (CollectionUtils.isEmpty(set))
return -1;
List<Integer> list = new ArrayList<>(set);
list.sort(Comparator.naturalOrder());
return list.get(0);
aop切面
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.es.user.annotation.DataOperateLog;
import com.es.user.domain.threadlocah.DataOperateLogThreadLocal;
import com.es.user.util.UUIDUtil;
import com.es.user.util.log.CompareObjUtil;
import com.es.user.util.log.OperationDataChange;
import com.es.user.util.log.OperationRecord;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.*;
/**
* author : wb
* File Name: DataOperateLogAspect
* Package Name: com.es.user.domain.aspect
* Date: 2022/5/24 15:17
* Copyright (c) 2022,All Rights Reserved.
*/
@Aspect
@Component
public class DataOperateLogAspect
private Logger logger = LoggerFactory.getLogger(DataOperateLogAspect.class);
@Autowired
private DataOperateLogThreadLocal dataOperateLogThreadLocal;
/**
* <p>
* 切面前执行
* </p>
*
* @param dataLog dataLog
* @return void
*/
@Before("@annotation(dataLog)")
public void beforeDataOperate(JoinPoint joinPoint, DataOperateLog dataLog)
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
String ClassName = methodSignature.getDeclaringTypeName();
DataOperateLogThreadLocal.THREADDATA_METHOD.set(ClassName+"#"+joinPoint.getSignature().getName());
DataOperateLogThreadLocal.DATA_CHANGES.set(new LinkedList<>());
DataOperateLogThreadLocal.JOIN_POINT.set(joinPoint);
DataOperateLogThreadLocal.DATA_LOG.set(dataLog);
DataOperateLogThreadLocal.THREADDATA_ID.set(UUID.randomUUID().toString().replace("-", "")+"-"+System.currentTimeMillis());
/**
* <p>
* 切面后执行
* </p>
*
* @param dataLog dataLog
* @return void
*/
@AfterReturning("@annotation(dataLog)")
public void afterDataOperate(DataOperateLog dataLog)
try
List<OperationDataChange> list = DataOperateLogThreadLocal.DATA_CHANGES.get();
if (CollectionUtils.isEmpty(list))
return;
list.forEach(change ->
List<?> oldData = change.getOldData();
if (CollectionUtils.isEmpty(oldData))
return;
List<Map<String, Object>> maps = change.getJdbcTemplate().queryForList(change.getQuerySql());
//Object obj = JSONObject.parseObject(JSON.toJSONString(maps.get(0)),change.getEntityType());
change.setNewData(maps);
);
this.compareAndTransfer(list);
catch (Exception e)
/**
* <p>
* 对比保存
* </p>
*
* @param list list
* @return void
*/
public void compareAndTransfer(List<OperationDataChange> list)
List<OperationRecord> saveData = new ArrayList<>();
list.forEach(change ->
List<?> oldData = change.getOldData();
List<?> newData = change.getNewData();
// 更新前后数据量不对必定是删除(逻辑删除)不做处理
if (newData == null)
return;
if (oldData == null)
return;
if (oldData.size() != newData.size())
return;
for (int i = 0; i < oldData.size(); i++)
try
String oldDataStr = JSON.toJSONString(oldData.get(i));
String newDataStr = JSON.toJSONString(newData.get(i));
String json = CompareObjUtil.campareJsonObject(oldDataStr,newDataStr);
OperationRecord operationRecord = new OperationRecord();
operationRecord.setChangeData(json);
operationRecord.setTransferData(JSON.toJSONString(change.getTransferData()));
operationRecord.setTableName(change.getTableName());
operationRecord.setBusinessProcessId(DataOperateLogThreadLocal.THREADDATA_ID.get().toString());
operationRecord.setId(UUIDUtil.randonUUID());
operationRecord.setOldObject(oldDataStr);
operationRecord.setNewObject(newDataStr);
operationRecord.setBusinessCallMethod(DataOperateLogThreadLocal.THREADDATA_METHOD.get().toString());
saveData.add(operationRecord);
catch (Exception e)
);
logger.info("要保存的操作记录数据:",JSON.toJSONString(saveData));
dataOperateLogThreadLocal.transfer();
DataOperateLogThreadLocal
import com.es.user.annotation.DataOperateLog;
import com.es.user.util.log.OperationDataChange;
import org.aspectj.lang.JoinPoint;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* author : wb
* File Name: DataOperateLogThreadLocal
* Package Name: com.es.user.domain.loca
* Date: 2022/5/20 16:26
* Copyright (c) 2022,All Rights Reserved.
*/
@Service
public class DataOperateLogThreadLocal
/**
* 注解
*/
public static final ThreadLocal<DataOperateLog> DATA_LOG = new ThreadLocal<>();
/**
* 切点
*/
public static final ThreadLocal<JoinPoint> JOIN_POINT = new ThreadLocal<>();
/**
* 数据变化
*/
public static final ThreadLocal<List<OperationDataChange>> DATA_CHANGES = new ThreadLocal<>();
/**
* 当前线程操作生成的唯一ID
*/
@SuppressWarnings("rawtypes")
public static final ThreadLocal THREADDATA_ID = new ThreadLocal();
/**
* 当前操作的调用的方法
*/
public static final ThreadLocal THREADDATA_METHOD = new ThreadLocal();
/**
* <p>
* 调用
* </p>
*
* @return void
*/
public void transfer()
DATA_CHANGES.remove();
DATA_LOG.remove();
JOIN_POINT.remove();
THREADDATA_ID.remove();
THREADDATA_METHOD.remove();
切面注解
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataOperateLog
/**
* 类型
*/
int type() default -1;
/**
* 标签
*/
String tag() default "";
/**
* 注释
*/
String note() default "";
工具类
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import java.lang.reflect.Field;
import java.util.*;
/**
* author : wb
* File Name: CompareObjUtil
* Package Name: com.es.user.util.log
* Date: 2022/5/24 17:43
* Copyright (c) 2022,All Rights Reserved.
*/
public class CompareObjUtil
/**
* @description 比较两个对象的不同
* @param
* @return
*/
public static List<Comparison> compareObj(Object beforeObj, Object afterObj) throws Exception
List<Comparison> diffs = new ArrayList<>();
if(beforeObj == null)
throw new RuntimeException("原对象不能为空");
if(afterObj == null)
throw new RuntimeException("新对象不能为空");
if(!beforeObj.getClass().isAssignableFrom(afterObj.getClass()))
throw new RuntimeException("两个对象不相同,无法比较");
//取出属性
Field[] beforeFields = beforeObj.getClass().getDeclaredFields();
Field[] afterFields = afterObj.getClass().getDeclaredFields();
Field.setAccessible(beforeFields, true);
Field.setAccessible(afterFields, true);
//遍历取出差异值
if(beforeFields != null && beforeFields.length > 0)
for(int i=0; i<beforeFields.length; i++)
Object beforeValue = beforeFields[i].get(beforeObj);
Object afterValue = afterFields[i].get(afterObj);
if((beforeValue != null && !"".equals(beforeValue) && !beforeValue.equals(afterValue)) || ((beforeValue == null || "".equals(beforeValue)) && afterValue != null))
Comparison comparison = new Comparison();
comparison.setField(beforeFields[i].getName());
comparison.setBefore(beforeValue);
comparison.setAfter(afterValue);
diffs.add(comparison);
return diffs;
/**
* @description 比较两个json串的不同
* @param
* @return
*/
public static String campareJsonObject(String oldJsonStr, String newJsonStr1)
//将字符串转换为json对象
JSON oldJson = JSON.parseObject(oldJsonStr);
JSON newJson = JSON.parseObject(newJsonStr1);
//递归遍历json对象所有的key-value,将其封装成path:value格式进行比较
Map<String, Object> oldMap = new LinkedHashMap<>();
Map<String, Object> newMap = new LinkedHashMap<>();
convertJsonToMap(oldJson, "", oldMap);
convertJsonToMap(newJson, "", newMap);
Map<String, Object> differenceMap = campareMap(oldMap, newMap);
//将最终的比较结果把不相同的转换为json对象返回
String jsonObject = convertMapToJson(differenceMap);
return jsonObject;
/**
* 将json数据转换为map存储用于比较
*
* @param json
* @param root
* @param resultMap
*/
private static void convertJsonToMap(Object json, String root, Map<String, Object> resultMap)
if (json instanceof JSONObject)
JSONObject jsonObject = ((JSONObject) json);
Iterator iterator = jsonObject.keySet().iterator();
while (iterator.hasNext())
Object key = iterator.next();
Object value = jsonObject.get(key);
String newRoot = "".equals(root) ? key + "" : root + "." + key;
if (value instanceof JSONObject || value instanceof JSONArray)
convertJsonToMap(value, newRoot, resultMap);
else
resultMap.put(newRoot, value);
else if (json instanceof JSONArray)
JSONArray jsonArray = (JSONArray) json;
for (int i = 0; i < jsonArray.size(); i++)
Object vaule = jsonArray.get(i);
String newRoot = "".equals(root) ? "[" + i + "]" : root + ".[" + i + "]";
if (vaule instanceof JSONObject || vaule instanceof JSONArray)
convertJsonToMap(vaule, newRoot, resultMap);
else
resultMap.put(newRoot, vaule);
/**
* 比较两个map,返回不同数据
*
* @param oldMap
* @param newMap
* @return
*/
private static Map<String, Object> campareMap(Map<String, Object> oldMap, Map<String, Object> newMap)
//遍历newMap,将newMap的不同数据装进oldMap,同时删除oldMap中与newMap相同的数据
campareNewToOld(oldMap, newMap);
//將舊的有新的沒有的數據封裝數據結構存在舊的裡面
campareOldToNew(oldMap);
return oldMap;
/**
* 將舊的有新的沒有的數據封裝數據結構存在舊的裡面
* @param oldMap
* @return
*/
private static void campareOldToNew(Map<String, Object> oldMap)
//统一oldMap中newMap不存在的数据的数据结构,便于解析
for (Iterator<Map.Entry<String, Object>> it = oldMap.entrySet().iterator(); it.hasNext(); )
Map.Entry<String, Object> item = it.next();
String key = item.getKey();
Object value = item.getValue();
int lastIndex = key.lastIndexOf(".");
if (!(value instanceof Map))
Map<String, Object> differenceMap = new HashMap<>();
differenceMap.put("oldValue", value);
differenceMap.put("newValue", "");
oldMap.put(key, differenceMap);
/**
* 將新的map與舊的比較,並將數據統一存在舊的裡面
* @param oldMap
* @param newMap
*/
private static void campareNewToOld(Map<String, Object> oldMap, Map<String, Object> newMap)
for (Iterator<Map.Entry<String, Object>> it = newMap.entrySet().iterator(); it.hasNext(); )
Map.Entry<String, Object> item = it.next();
String key = item.getKey();
Object newValue = item.getValue();
Map<String, Object> differenceMap = new HashMap<>();
int lastIndex = key.lastIndexOf(".");
String lastPath = key.substring(lastIndex + 1).toLowerCase();
if (oldMap.containsKey(key))
Object oldValue = oldMap.get(key);
if (newValue.equals(oldValue))
oldMap.remove(key);
continue;
else
differenceMap.put("oldValue", oldValue);
differenceMap.put("newValue", newValue);
oldMap.put(key, differenceMap);
else
differenceMap.put("oldValue", "");
differenceMap.put("newValue", newValue);
oldMap.put(key, differenceMap);
/**
* 将已经找出不同数据的map根据key的层级结构封装成json返回
*
* @param map
* @return
*/
private static String convertMapToJson(Map<String, Object> map)
JSONObject resultJSONObject = new JSONObject();
for (Iterator<Map.Entry<String, Object>> it = map.entrySet().iterator(); it.hasNext(); )
Map.Entry<String, Object> item = it.next();
String key = item.getKey();
Object value = item.getValue();
String[] paths = key.split("\\\\.");
int i = 0;
Object remarkObject = null;//用於深度標識對象
int indexAll = paths.length - 1;
while (i <= paths.length - 1)
String path = paths[i];
if (i == 0)
//初始化对象标识
if (resultJSONObject.containsKey(path))
remarkObject = resultJSONObject.get(path);
else
if (indexAll > i)
if (paths[i + 1].matches("\\\\[[0-9]+\\\\]"))
remarkObject = new JSONArray();
else
remarkObject = new JSONObject();
resultJSONObject.put(path, remarkObject);
else
resultJSONObject.put(path, value);
i++;
continue;
if (path.matches("\\\\[[0-9]+\\\\]")) //匹配集合对象
int startIndex = path.lastIndexOf("[");
int endIndext = path.lastIndexOf("]");
int index = Integer.parseInt(path.substring(startIndex + 1, endIndext));
if (indexAll > i)
if (paths[i + 1].matches("\\\\[[0-9]+\\\\]"))
while (((JSONArray) remarkObject).size() <= index)
if(((JSONArray) remarkObject).size() == index)
((JSONArray) remarkObject).add(index,new JSONArray());
else
((JSONArray) remarkObject).add(null);
else
while(((JSONArray) remarkObject).size() <= index)
if(((JSONArray) remarkObject).size() == index)
((JSONArray) remarkObject).add(index,new JSONObject());
else
((JSONArray) remarkObject).add(null);
remarkObject = ((JSONArray) remarkObject).get(index);
else
while(((JSONArray) remarkObject).size() <= index)
if(((JSONArray) remarkObject).size() == index)
((JSONArray) remarkObject).add(index, value);
else
((JSONArray) remarkObject).add(null);
else
if (indexAll > i)
if (paths[i + 1].matches("\\\\[[0-9]+\\\\]"))
if(!((JSONObject) remarkObject).containsKey(path))
((JSONObject) remarkObject).put(path, new JSONArray());
else
if(!((JSONObject) remarkObject).containsKey(path))
((JSONObject) remarkObject).put(path, new JSONObject());
remarkObject = ((JSONObject) remarkObject).get(path);
else
((JSONObject) remarkObject).put(path, value);
i++;
return JSON.toJSONString(resultJSONObject);
import java.io.Serializable;
/**
* author : wb
* File Name: Comparison
* Package Name: com.es.user.util.log
* Date: 2022/5/24 17:43
* Copyright (c) 2022,All Rights Reserved.
*/
public class Comparison implements Serializable
//字段
private String Field;
//字段旧值
private Object before;
//字段新值
private Object after;
public String getField()
return Field;
public void setField(String field)
Field = field;
public Object getBefore()
return before;
public void setBefore(Object before)
this.before = before;
public Object getAfter()
return after;
public void setAfter(Object after)
this.after = after;
import org.springframework.jdbc.core.JdbcTemplate;
import java.io.Serializable;
import java.util.List;
/**
* author : wb
* File Name: DataChange
* Package Name: com.es.user.util.log
* Date: 2022/5/24 15:14
* Copyright (c) 2022,All Rights Reserved.
*/
public class OperationDataChange implements Serializable
/**
* 当前数据变更的流程ID
*/
private String dataId;
/**
* jdbctemplate
*/
private JdbcTemplate jdbcTemplate;
/**
* sqlStatement
*/
private String querySql;
/**
* 表名
*/
private String tableName;
/**
* where 条件
*/
private String whereSql;
/**
* 对应实体类
*/
private Class<?> entityType;
/**
* 更新前数据
*/
private List<?> oldData;
/**
* 更新后数据
*/
private List<?> newData;
/**
* 传递的数据
*/
private List<?> transferData;
public List<?> getTransferData()
return transferData;
public void setTransferData(List<?> transferData)
this.transferData = transferData;
public String getDataId()
return dataId;
public void setDataId(String dataId)
this.dataId = dataId;
public JdbcTemplate getJdbcTemplate()
return jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate)
this.jdbcTemplate = jdbcTemplate;
public String getQuerySql()
return querySql;
public void setQuerySql(String querySql)
this.querySql = querySql;
public String getTableName()
return tableName;
public void setTableName(String tableName)
this.tableName = tableName;
public String getWhereSql()
return whereSql;
public void setWhereSql(String whereSql)
this.whereSql = whereSql;
public Class<?> getEntityType()
return entityType;
public void setEntityType(Class<?> entityType)
this.entityType = entityType;
public List<?> getOldData()
return oldData;
public void setOldData(List<?> oldData)
this.oldData = oldData;
public List<?> getNewData()
return newData;
public void setNewData(List<?> newData)
this.newData = newData;
import java.io.Serializable;
/**
* author : wb
* File Name: OperationRecords
* Package Name: com.es.user.util.log
* Date: 2022/5/24 18:52
* Copyright (c) 2022,All Rights Reserved.
*/
public class OperationRecord implements Serializable
private Long id;
/**
* 操作业务流程ID
*/
private String businessProcessId;
/**
* 变更之后数据发生的变更
*/
private String changeData;
/**
* 传递的值
*/
private String transferData;
/**
* 原数据值
*/
private String oldObject;
/**
* 新数据值
*/
private String newObject;
/**
* 操作的表明
*/
private String tableName;
/**
* 业务调用的方法
*/
private String businessCallMethod;
public Long getId()
return id;
public void setId(Long id)
this.id = id;
public String getChangeData()
return changeData;
public void setChangeData(String changeData)
this.changeData = changeData;
public String getTransferData()
return transferData;
public void setTransferData(String transferData)
this.transferData = transferData;
public String getOldObject()
return oldObject;
public void setOldObject(String oldObject)
this.oldObject = oldObject;
public String getNewObject()
return newObject;
public void setNewObject(String newObject)
this.newObject = newObject;
public String getBusinessProcessId()
return businessProcessId;
public void setBusinessProcessId(String businessProcessId)
this.businessProcessId = businessProcessId;
public String getTableName()
return tableName;
public void setTableName(String tableName)
this.tableName = tableName;
public String getBusinessCallMethod()
return businessCallMethod;
public void setBusinessCallMethod(String businessCallMethod)
this.businessCallMethod = businessCallMethod;
调用实现
@Service
public class UserInfoBL
/**
* 变更用户数据
*
* @param dto
*/
@DataOperateLog
public void updateSysUserInfo(UserInfoDTO dto)
userInfoMapper.updateSysUserInfo(dto);
import com.es.user.domain.bl.app.UserInfoBL;
import com.es.user.dto.app.UserInfoDTO;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles(value="dev")
public class UserTest
@Autowired
private UserInfoBL userInfoBL;
@Test
public void testUpdateUserInfo()
UserInfoDTO infoDTO = new UserInfoDTO();
infoDTO.setUserId("8639115745654494218");
infoDTO.setState(0);
userInfoBL.updateSysUserInfo(infoDTO);
调用打印结果
[
"businessCallMethod":"com.yijiupi.himalaya.easysale.user.domain.bl.app.UserInfoBL#updateSysUserInfo",
"businessProcessId":"be5ec2405d64427fa38185422e2e9484-1653446567181",
"changeData":"\\"last_update_time\\":\\"newValue\\":1653446571000,\\"oldValue\\":1648545800000,\\"state\\":\\"newValue\\":0,\\"oldValue\\":1",
"id":5175759873968579967,
"newObject":"\\"id\\":8639115745654494218,\\"user_name\\":\\"13871905563\\",\\"user_password\\":\\"e10adc3949ba59abbe56e057f20f883e\\",\\"mobile_no\\":\\"13871905563\\",\\"nick_name\\":\\"13871905563\\",\\"wx_app_id\\":\\"oBl7n5Z03UUGUVSJXlP--l8XsDG0\\",\\"state\\":0,\\"create_time\\":1636447507000,\\"last_update_time\\":1653446571000,\\"operator\\":\\"8639115745654494218\\",\\"user_type\\":5,\\"login_user_name\\":\\"9UBUDGZME\\",\\"data_source\\":4",
"oldObject":"\\"id\\":8639115745654494218,\\"user_name\\":\\"13871905563\\",\\"user_password\\":\\"e10adc3949ba59abbe56e057f20f883e\\",\\"mobile_no\\":\\"13871905563\\",\\"nick_name\\":\\"13871905563\\",\\"wx_app_id\\":\\"oBl7n5Z03UUGUVSJXlP--l8XsDG0\\",\\"state\\":1,\\"create_time\\":1636447507000,\\"last_update_time\\":1648545800000,\\"operator\\":\\"8639115745654494218\\",\\"user_type\\":5,\\"login_user_name\\":\\"9UBUDGZME\\",\\"data_source\\":4",
"tableName":"dealer_login_user",
"transferData":"[\\"state\\":0,\\"userId\\":\\"8639115745654494218\\"]"
]
项目源码地址整合上述代码:wb54979 / easysale-framework · GitCode
以上是关于spring aop mybatis puls 审计日志数据操作前操作后对比记录的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot + Mybatis Plus + ClickHouse 轻松实现增删改查,看了必懂。。
SpringBoot + Mybatis-puls + ClickHouse (分页查询添加修改删除)