package com.itl.iap.common.base.interceptor;
import com.itl.iap.common.base.dto.UserTDto;
import com.itl.iap.common.base.utils.UserUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.defaults.DefaultSqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;
/**
* @version 1.1
* 版本更新,對象如果是集合采用遞歸的方式添加
*/
@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
@Slf4j
@SuppressWarnings("all")
public class SqlInterceptor implements Interceptor {
/**
* 建立時間
*/
private static final String CREATE_TIME = "createDate";
private static final String CREATER = "creater";
/**
* 更新時間
*/
private static final String UPDATE_TIME = "lastUpdateDate";
private static final String UPDATE_BY = "lastUpdateBy";
@Autowired
private UserUtil userUtil;
@Override
public Object intercept(Invocation invocation) throws Throwable {
String name = invocation.getMethod().getName();
if (name.equals("update") || name.equals("install")) {
return invokeUpdate(invocation);
} else {
return invocation.proceed();
}
}
// 修改操作
private Object invokeUpdate(Invocation invocation) throws Exception {
// 擷取第一個參數
Object[] args1 = invocation.getArgs();
// 去除null
List<Object> objList = Arrays.stream(args1).filter(x -> x != null).collect(Collectors.toList());
MappedStatement ms = null;
Object args = null; // 擷取參數
// 指派
for (Object obj : objList) {
if (obj instanceof MappedStatement) {
ms = (MappedStatement) obj;
} else if (obj instanceof Object) {
args = obj;
}
}
if (ms == null || args == null) {
return invocation.proceed();
}
SqlCommandType sqlCommandType = ms.getSqlCommandType();
// 判斷參數類型 是不是MapperMethod.ParamMap 是 就循環更改 不是就是對象直接更改
if (args instanceof MapperMethod.ParamMap) {
MapperMethod.ParamMap<Object> mapObj = (MapperMethod.ParamMap<Object>) args;
for (Map.Entry<String, Object> obj : mapObj.entrySet()) {
Object paramObj = mapObj.get(obj.getKey());
if (paramObj instanceof List) {
this.objList(paramObj, ms);
} else {
Field[] fields = paramObj.getClass().getDeclaredFields();
this.upField(fields, ms, args);
}
}
} else if (args instanceof DefaultSqlSession.StrictMap) {
DefaultSqlSession.StrictMap<Object> mapObj = (DefaultSqlSession.StrictMap<Object>) args;
for (Map.Entry<String, Object> obj : mapObj.entrySet()) {
Object paramObj = mapObj.get(obj.getKey());
if (paramObj instanceof List) {
this.objList(paramObj, ms);
} else {
Field[] fields = paramObj.getClass().getDeclaredFields();
this.upField(fields, ms, args);
}
}
} else {
Field[] fields = args.getClass().getDeclaredFields();
this.upField(fields, ms, args);
}
return invocation.proceed();
}
/**
* 如果是集合就遞歸
*
* @param paramObj List 對象
* @param ms MappedStatement
*/
private void objList(Object paramObj, MappedStatement ms) {
List<Object> listObj = (ArrayList<Object>) paramObj;
for (Object obj : listObj) {
if (obj instanceof List) {
this.objList(obj, ms);
}
Field[] declaredFields = obj.getClass().getDeclaredFields();
this.upField(declaredFields, ms, obj);
}
}
/**
* 開始執行修改方法
*
* @param fields 反射擷取字段清單
* @param ms MappedStatement
* @param args 對象參數
*/
private void upField(Field[] fields, MappedStatement ms, Object args) {
// 如果 insert 語句 則添加建立時間建立人 修改時間和修改人
if (ms.getSqlCommandType() == SqlCommandType.INSERT) {
this.setAllParams(fields, args, CREATE_TIME, new Date());
this.setAllParams(fields, args, CREATER, UPDATE_BY.toString());
this.setAllParams(fields, args, UPDATE_BY, UPDATE_BY.toString());
this.setAllParams(fields, args, UPDATE_TIME, new Date());
// 如果是update語句 則添加修改時間修改人
} else if (ms.getSqlCommandType() == SqlCommandType.UPDATE) {
this.setAllParams(fields, args, UPDATE_BY, UPDATE_BY.toString());
this.setAllParams(fields, args, UPDATE_TIME, new Date());
}
}
/**
* 根據傳遞參數放進行修改
*
* @param fields 反射存在的參數
* @param obj 需要改變的對象
* @param valueKey 變更的字段
* @param valObj 變更參數類型
*/
private void setAllParams(Field[] fields, Object obj, String valueKey, Object valObj) {
UserTDto user = this.getUser();
for (int i = 0; i < fields.length; i++) {
if (valueKey.toLowerCase().equals(fields[i].getName().toLowerCase())) {
try {
if (valObj instanceof Date) {
fields[i].setAccessible(true);
fields[i].set(obj, new Date());
fields[i].setAccessible(false);
}
if (user != null && user.getUserName() != null) {
if (valObj instanceof String) {
fields[i].setAccessible(true);
fields[i].set(obj, user.getUserName());
fields[i].setAccessible(false);
}
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
// 擷取使用者
private UserTDto getUser() {
return userUtil.getUser();
}
@Override
public Object plugin(Object target) {
if (target instanceof Executor) {
return Plugin.wrap(target, this);
} else {
return target;
}
}
@Override
public void setProperties(Properties properties) {
}
}