• Mybatis使用拦截器自定义审计处理


        void test_save_1(@Param("relatedBookCategoryEntity") RelatedBookCategoryEntity relatedBookCategoryEntity11, BookEntity bookEntity11, String categoryName11,Integer age11);
        
    void test_save_2(RelatedBookCategoryEntity relatedBookCategoryEntity22, BookEntity bookEntity22, String categoryName22,Integer age22);
        
       void test_save_3(String categoryName33);
        
      
    
        void test_save_4( String categoryName22,Integer age22);
         

        

      void test_save_5(RelatedBookCategoryEntity relatedBookCategoryEntity22);
        
          

       


    以上是测试的接口,方法签名下方图片是拦截器内部形参的值结构。

    以下是Java代码,实现mybatis的Interceptor接口

    package cn.dmahz.config;
    
    import cn.dmahz.dao.mapper.RelatedBookCategoryMapper;
    import cn.dmahz.entity.Base;
    import cn.dmahz.entity.BookEntity;
    import cn.dmahz.entity.RelatedBookCategoryEntity;
    import cn.dmahz.utils.MyReflectUtils;
    import cn.dmahz.utils.SecurityContextHolderUtils;
    import org.apache.commons.lang3.StringUtils;
    import org.apache.ibatis.annotations.Param;
    import org.apache.ibatis.executor.Executor;
    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.springframework.data.annotation.*;
    import org.springframework.stereotype.Component;
    
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.lang.reflect.Parameter;
    import java.sql.Statement;
    import java.util.*;
    
    /**
     * @author Dream
     */
    @Component
    @Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class }),@Signature(type= StatementHandler.class,method = "parameterize",args = {Statement.class}) })
    public class MybatisEntityPluginInterceptor implements Interceptor {
    
        @Override
        public Object intercept(Invocation invocation) throws Throwable {
    
            Object[] args = invocation.getArgs();
            if(args[0] instanceof MappedStatement){
                // 映射的各种信息,SQL信息、接口方法对应的参数、接口方法的全名称等等
                MappedStatement mappedStatement = (MappedStatement) args[0];
    
                // 获取执行语句的类型
                SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
    
    
                if(args[1] instanceof HashMap<?, ?>){
                    HashMap<?,?> hashMap = (HashMap<?, ?>) args[1];
                    // 这里分别处理每个参数的实体注入
                    // mappedStatement.getId()   -> 获取方法的全路径 ;例如: cn.xxx.xxx.xxx.ClassName.methodName
                    Method methodInMapper = MyReflectUtils.getMethodInMapper(mappedStatement.getId());
                    String[] paramKeys = parseParamKeysByMethod(methodInMapper);
                    for(String key:paramKeys){
                        Object o = hashMap.get(key);
                        if(o instanceof List){
                            List<?> list = (List<?>) o;
                            for(Object entity:list){
                                Field[] allAuditFields = MyReflectUtils.getAllAuditFields(entity.getClass());
                                setAuditField(sqlCommandType,entity,allAuditFields);
                            }
                        }else if(o instanceof Base){
                            // 这里处理不是集合的情况,通过继承 cn.dmahz.entity.Base,可证明为Java Bean
                            Field[] allAuditFields = MyReflectUtils.getAllAuditFields(o.getClass());
                            setAuditField(sqlCommandType,o,allAuditFields);
                        }
                    }
                } else if(args[1] instanceof Base){
                    Object o =args[1];
                    // 这里处理不是集合的情况,通过继承 cn.dmahz.entity.Base,可证明为Java Bean
                    Field[] allAuditFields = MyReflectUtils.getAllAuditFields(o.getClass());
                    setAuditField(sqlCommandType,o,allAuditFields);
                }
            }
    
            // 让拦截器继续处理剩余的操作
            return invocation.proceed();
        }
    
        /**
         * 解析方法的形参的key值,key值用于在 ParamMap中查找值,进行填充审计字段
         * @param method
         */
        private String[] parseParamKeysByMethod(Method method){
            ArrayList<String> keyList = new ArrayList<>();
            Parameter[] parameters = method.getParameters();
            for (Parameter parameter:parameters) {
                Param parameterAnnotation = parameter.getAnnotation(Param.class);
                if(parameterAnnotation != null){
                    keyList.add(parameterAnnotation.value());
                }else {
                    // 形参名称
                    String name = parameter.getName();
                    // 类型的简写名称
    //                String simpleName = parameter.getType().getSimpleName();
                    if(StringUtils.isNotBlank(name)){
                        keyList.add(name);
                    }
                }
            }
            return keyList.toArray(new String[0]);
        }
    
        /**
         * 包装一下重复的代码,方便调用
         * @param sqlCommandType
         * @param o
         * @param fields
         * @throws IllegalAccessException
         */
        private void setAuditField(SqlCommandType sqlCommandType,Object o,Field[] fields) throws IllegalAccessException{
            for(Field field:fields){
                setAuditField(sqlCommandType,o,field);
            }
        }
    
        /**
         * 设置审计字段,包括创建人,主键ID,创建时间,更新人,更新时间。
         * @param sqlCommandType
         * @param o
         * @param field
         * @throws IllegalAccessException
         */
        private void setAuditField(SqlCommandType sqlCommandType,Object o,Field field) throws IllegalAccessException {
            if(sqlCommandType == SqlCommandType.INSERT){
                if(field.isAnnotationPresent(CreatedBy.class)){
                    String currentUserId;
                    try {
                        currentUserId = SecurityContextHolderUtils.getCurrentUserId();
                    } catch (NullPointerException e) {
                        //这里仅作测试,忽略空指针异常
                        currentUserId = "非Web环境,当前用户ID测试值(创建值)";
                    }
                    field.set(o,currentUserId);
                }else if(field.isAnnotationPresent(CreatedDate.class)){
                    field.set(o,System.currentTimeMillis());
                }else if(field.isAnnotationPresent(Id.class)){
                    String uuId = UUID.randomUUID().toString();
                    field.set(o,uuId.replace("-",""));
                }
            }else if(sqlCommandType == SqlCommandType.UPDATE){
                if(field.isAnnotationPresent(LastModifiedBy.class)){
                    String currentUserId;
                    try {
                        currentUserId = SecurityContextHolderUtils.getCurrentUserId();
                    } catch (NullPointerException e) {
                        //这里仅作测试,忽略空指针异常
                        currentUserId = "非Web环境,当前用户ID测试值(更新值)";
                    }
                    field.set(o,currentUserId);
                }else if(field.isAnnotationPresent(LastModifiedDate.class)){
                    field.set(o,System.currentTimeMillis());
                }
            }
        }
    
        public static void main(String[] args) throws InterruptedException, NoSuchMethodException {
    
            Method test_save_1 = RelatedBookCategoryMapper.class.getDeclaredMethod("test_save_1", RelatedBookCategoryEntity.class, BookEntity.class, String.class);
    //        parseParamKeysByMethod(test_save_1);
        }
    }
    View Code
    复制请注明出处,在世界中挣扎的灰太狼
  • 相关阅读:
    c语言 414 根据输入的整数,循环显示1234567890
    c语言 47 编写一段程序,显示小于输入的整数的所有2的乘方。
    c语言49 交替输出正负号,当输入0以下时什么也不显示
    c语言48 改写48的程序,当输入的值小于1时不输出换行符
    c语言 411 逆向输出输入的整数值(同时输出原始数据)
    c语言47 显示出小于输入的整数的所有2的乘方
    c语言412 输入一个整数值显示其位数
    c语言415 输出标准身高体重对照表
    c语言413 求1到n的和
    c语言 410 输出连续* \n
  • 原文地址:https://www.cnblogs.com/XingXiaoMeng/p/14318694.html
Copyright © 2020-2023  润新知