配置文件装载拦截器
拦截器代码:
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
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.session.Configuration;
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.jdbc.core.JdbcTemplate;
import java.text.DateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.stream.Collectors;
/**
* 记录更新内容
*/
@Slf4j
@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class,
Object.class})})
public class MybatisUpdateInterceptor implements Interceptor {
private static String [] officeIdNames = new String[]{"OFFICE_ID","OFFICEID","PK_OFFICE_ID"};
@Lazy
@Autowired
private SysAuditUpdateLogMapper sysAuditUpdateLogMapper;
@Override
public Object intercept(Invocation invocation) throws Throwable {
Object logId = ThreadLocalUtil.get("logId");
if(logId != null){
log.debug("审计日志主键"+logId.toString());
//解决拦截器执行两次的问题
String name = invocation.getTarget().getClass().getName();
if(!"org.apache.ibatis.executor.CachingExecutor".equals(name)){
MappedStatement mappedStatement = (MappedStatement)invocation.getArgs()[0];
//0.sql参数获取
Object parameter = null;
if (invocation.getArgs().length > 1) {
parameter = invocation.getArgs()[1];
}
//1.获取sqlId
String sqlId = mappedStatement.getId();
BoundSql boundSql = mappedStatement.getBoundSql(parameter);
Configuration configuration = mappedStatement.getConfiguration();
//获取真实的sql语句
String sql = getSql(configuration, boundSql, sqlId, 0);
if(!sql.contains("INSERT")){
//2.判断是否有officeId
if (hasOfficeId(sql,officeIdNames)) {
log.warn("{}", sql);
} else {
log.debug("{}", sql);
}
//截取表名
String tableName = sql.substring(sql.indexOf("UPDATE") + 6, sql.indexOf("SET"));
//截取where条件
String where = sql.substring(sql.indexOf("WHERE"));
String selectSql = "SELECT * FROM " + tableName + where;
log.debug(selectSql);
List<Map<String, Object>> maps = sysAuditUpdateLogMapper.queryForList(selectSql);
//截取出要更新的参数
String paras = sql.substring(sql.indexOf("SET") + 3, sql.indexOf("WHERE"));
paras = paras.replace("=", ":");
JSONObject jsonObject = JSONObject.parseObject("{" + paras + "}");
log.debug(jsonObject.toString());
log.debug(maps.toString());
//查询表注释
List<Map<String, Object>> colMap = sysAuditUpdateLogMapper.queryForComment(tableName.trim());
Map<Object,Object> columnName = new HashMap<>();
colMap.forEach(a->{
columnName.put(a.get("COLUMN_NAME"),a.get("COLUMN_COMMENT"));
});
//比对是否跟新
for (Map<String, Object> stringObjectMap : maps){
//所修改内容描述
StringBuffer desc = new StringBuffer();
//变更的所有值
StringBuffer buffer = new StringBuffer("{" );
for(Map.Entry entry :jsonObject.entrySet()){
for(Map.Entry entry2 :stringObjectMap.entrySet()){
if(entry.getKey().equals(entry2.getKey())){
if(!entry.getValue().equals(entry2.getValue())){
buffer.append(entry.getKey() + ":" +entry.getValue() +",");
desc.append(Objects.isNull(columnName.get(entry.getKey()))? entry.getKey(): columnName.get(entry.getKey()))
.append(" 由 ").append(entry2.getValue()).append(" 修改为 ")
.append(entry.getValue()).append(",");
}
}
}
}
log.debug(buffer.toString());
}
}
}
}
return invocation.proceed();
}
/**
* 判断sql语句中是否包含officeId字段
*
* @param sql sql语句
* @return
*/
private boolean hasOfficeId(String sql,String[] officeIdNames) {
//office ID 的可能名称
if (sql == null || sql.trim().length() == 0) {
return false;
}
String afterWhereStatement = sql.toUpperCase().substring(sql.indexOf("WHERE"));
for (String officeIdName : officeIdNames){
if(afterWhereStatement.indexOf(officeIdName) > 0){
return true;
}
}
return false;
}
private static String getSql(Configuration configuration, BoundSql boundSql,
String sqlId, long time) {
String sql = showSql(configuration, boundSql);
StringBuilder str = new StringBuilder(100);
// str.append(sqlId);
// str.append(":");
str.append(sql);
return str.toString();
}
private static String getParameterValue(Object obj) {
String value = null;
if (obj instanceof String) {
value = "'" + obj.toString() + "'";
} else if (obj instanceof Date) {
DateFormat formatter = DateFormat.getDateTimeInstance(
DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.CHINA);
value = "'" + formatter.format(obj) + "'";
} else {
if (obj != null) {
value = obj.toString();
} else {
value = "";
}
}
return value;
}
private static String showSql(Configuration configuration, BoundSql boundSql) {
Object parameterObject = boundSql.getParameterObject();
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
String sql = boundSql.getSql().replaceAll("[\\s]+", " ");
if (!parameterMappings.isEmpty() && parameterObject != null) {
TypeHandlerRegistry typeHandlerRegistry = configuration
.getTypeHandlerRegistry();
if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
sql = sql.replaceFirst("\\?",
Matcher.quoteReplacement(getParameterValue(parameterObject)));
} else {
MetaObject metaObject = configuration
.newMetaObject(parameterObject);
for (ParameterMapping parameterMapping : parameterMappings) {
String propertyName = parameterMapping.getProperty();
if (metaObject.hasGetter(propertyName)) {
Object obj = metaObject.getValue(propertyName);
sql = sql.replaceFirst("\\?", Matcher.quoteReplacement(getParameterValue(obj)));
} else if (boundSql.hasAdditionalParameter(propertyName)) {
Object obj = boundSql
.getAdditionalParameter(propertyName);
sql = sql.replaceFirst("\\?", Matcher.quoteReplacement(getParameterValue(obj)));
} else {
sql = sql.replaceFirst("\\?", "缺失");
}//打印出缺失,提醒该参数缺失并防止错位
}
}
}
return sql;
}
}
注意:注入的时候加上@Lazy注解,不然回报循环引用