Mybatis拦截器插入和修改时自动填充注入审计字段(无侵入性)

@Data
public class BaseEntity {

    @JsonSerialize(using = ToStringSerializer.class)
    private Long id;

    private Long createBy;

    @JsonFormat( pattern = "yyyy年MM月dd日 HH时mm分ss秒")
    private LocalDateTime createTime;

    private Long updateBy;

    @JsonFormat( pattern = "yyyy年MM月dd日 HH时mm分ss秒")
    private LocalDateTime updateTime;

    private Integer delFlag;
}
package org.yangmy.tide.common.core.config;

import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.builder.StaticSqlSource;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.mapping.SqlSource;
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.springframework.stereotype.Component;
import org.yangmy.tide.common.core.utils.BaseEntity;
import org.yangmy.tide.common.security.SecurityUtils;

import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.util.*;

/**
 * mybatis拦截器实现自动填充审计字段,原创
 * @author YangMingYang
 * @since 2022/5/10
 */
@Component
@Intercepts({@Signature(method = "update", type = Executor.class, args = {MappedStatement.class, Object.class})})
public class IbatisAuditDataInterceptor implements Interceptor {

    private final Set<String> cache=new HashSet<>();

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object[] args = invocation.getArgs();
        MappedStatement ms = (MappedStatement) args[0];
        Object params=args[1];
        SqlSource newSqlSource=null;
        if (ms.getSqlCommandType()==SqlCommandType.INSERT) {
            //重写sql语句增加审计字段
            String sql=ms.getSqlSource().getBoundSql(null).getSql();
            String newSql = insertAudit(sql);

            //创建新的参数隐射
            List<ParameterMapping> newParameterMappings=new ArrayList<>();
            ParameterMapping createByMapping=new ParameterMapping.Builder(ms.getConfiguration(),"createBy",Object.class).build();
            ParameterMapping createTimeMapping=new ParameterMapping.Builder(ms.getConfiguration(),"createTime",Object.class).build();
            ParameterMapping updateByMapping=new ParameterMapping.Builder(ms.getConfiguration(),"updateBy",Object.class).build();
            ParameterMapping updateTimeMapping=new ParameterMapping.Builder(ms.getConfiguration(),"updateTime",Object.class).build();
            ParameterMapping delFlagMapping=new ParameterMapping.Builder(ms.getConfiguration(),"delFlag",Object.class).build();
            newParameterMappings.add(createByMapping);
            newParameterMappings.add(createTimeMapping);
            newParameterMappings.add(updateByMapping);
            newParameterMappings.add(updateTimeMapping);
            newParameterMappings.add(delFlagMapping);
            newParameterMappings.addAll(ms.getSqlSource().getBoundSql(null).getParameterMappings());

            //创建新的SqlSource
            newSqlSource=new StaticSqlSource(ms.getConfiguration(),newSql,newParameterMappings);

            //填充审计字段
            if(params instanceof BaseEntity){
                BaseEntity baseEntity=(BaseEntity) params;
                baseEntity.setCreateBy(Long.valueOf(Objects.requireNonNull(SecurityUtils.getUserId())));
                baseEntity.setCreateTime(LocalDateTime.now());
                baseEntity.setUpdateBy(Long.valueOf(Objects.requireNonNull(SecurityUtils.getUserId())));
                baseEntity.setUpdateTime(LocalDateTime.now());
                baseEntity.setDelFlag(0);
            }else if(params instanceof MapperMethod.ParamMap){
                MapperMethod.ParamMap<Object> map= (MapperMethod.ParamMap) params;
                map.put("createBy",SecurityUtils.getUserId());
                map.put("createTime",LocalDateTime.now());
                map.put("updateBy",SecurityUtils.getUserId());
                map.put("updateTime",LocalDateTime.now());
                map.put("delFlag",0);
            }

            //修改sqlSource
            if(!cache.contains(ms.getId())){
                Field msField = invocation.getArgs()[0].getClass().getDeclaredField("sqlSource");
                msField.setAccessible(true);
                msField.set(invocation.getArgs()[0],newSqlSource);
                cache.add(ms.getId());
            }
        }
        if (ms.getSqlCommandType()==SqlCommandType.UPDATE) {
            //重写sql语句增加审计字段
            String source=ms.getSqlSource().getBoundSql(null).getSql();
            String newSql=updateAudit(source);

            //创建新的参数隐射
            List<ParameterMapping> newParameterMappings=new ArrayList<>();
            ParameterMapping updateByMapping=new ParameterMapping.Builder(ms.getConfiguration(),"updateBy",Object.class).build();
            ParameterMapping updateTimeMapping=new ParameterMapping.Builder(ms.getConfiguration(),"updateTime",Object.class).build();
            newParameterMappings.add(updateByMapping);
            newParameterMappings.add(updateTimeMapping);
            newParameterMappings.addAll(ms.getSqlSource().getBoundSql(null).getParameterMappings());

            //创建新的SqlSource
            newSqlSource=new StaticSqlSource(ms.getConfiguration(),newSql,newParameterMappings);

            //填充审计字段
            if(params instanceof BaseEntity){
                BaseEntity baseEntity=(BaseEntity) params;
                baseEntity.setUpdateBy(Long.valueOf(Objects.requireNonNull(SecurityUtils.getUserId())));
                baseEntity.setUpdateTime(LocalDateTime.now());
            }else{
                MapperMethod.ParamMap<Object> map= (MapperMethod.ParamMap) params;
                map.put("updateBy",SecurityUtils.getUserId());
                map.put("updateTime",LocalDateTime.now());
            }

            //修改sqlSource
            if(!cache.contains(ms.getId())){
                Field msField = invocation.getArgs()[0].getClass().getDeclaredField("sqlSource");
                msField.setAccessible(true);
                msField.set(invocation.getArgs()[0],newSqlSource);
                cache.add(ms.getId());
            }
        }

        //修改参数值
        invocation.getArgs()[1]=params;
        return invocation.proceed();
    }

    public String insertAudit(String source){
        char[] chars = source.toCharArray();
        StringBuilder newSql=new StringBuilder();
        boolean afterFormalParam=false;
        for (char c : chars) {
            String cStr=String.valueOf(c);
            newSql.append(cStr);
            if (cStr.equals("(")){
                if(afterFormalParam){
                    newSql.append("?,?,?,?,?,");
                }else {
                    newSql.append("create_by,create_time,update_by,update_time,del_flag,");
                }
            }
            if(cStr.equals(")")){
                afterFormalParam=true;
            }
        }
        return newSql.toString();
    }

    public String updateAudit(String source){
        String[] strArray = source.split("\\s+");
        StringBuilder newSql=new StringBuilder();
        boolean afterSet=false;
        for (String s : strArray) {
            if(afterSet){
                s="update_by=?,update_time=?,"+s;
                afterSet=false;
            }
            if(s.equals("set")||s.equals("SET")){
                afterSet=true;
            }
            newSql.append(s).append(" ");
        }
        return newSql.toString();
    }

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值