美文网首页Mybatis随笔-生活工作点滴
Mybatis自定义拦截器,处理通用接口

Mybatis自定义拦截器,处理通用接口

作者: 东方不喵 | 来源:发表于2019-07-11 00:31 被阅读17次

    在日常开发业务场景中,经常要遇到对 实体进行通用性操作,如:

    1. 进行持久化时,出现的保存 创建人信息
    2. 更新数据时候,通用更新 操作人信息
    3. 指定接口自定义主键,等
      为了解决这类问题,可以采用AOP 也可以采用拦截器,以下是采用MyBatis拦截器进行实现的
    设置通用实体参数
    @Data
    public class BaseEntity {
    
        @TableId
        private String id;
    
        private Date createTime;
    
        /**
         *  删除状态:
         *  1 : 已删除
         *  0 :未删除
         */
        @Column(nullable = false)
        private Integer isDeleted;
    }
    
    @Data
    @MappedSuperclass
    public class CommonBaseEntity extends BaseEntity implements CreatorSetterImpl, UpdaterSetterImpl {
    
        /**
         *  创建人ID
         */
        private String creatorId;
    
        /**
         *  创建人姓名
         */
        private String creatorName;
    
        /**
         *  最后更新人ID
         */
        private String updaterId;
    
        /**
         *  最后更新人姓名
         */
        private String updaterName;
    
        /**
         *  最后更新时间
         */
        private Date updateTime;
    
    }
    
    
    创建用户接口 CreatorSetterImpl
    public interface CreatorSetterImpl {
    
        void setCreatorId(String creatorId);
    
        void setCreatorName(String creatorName);
    
    }
    
    更新用户接口 UpdaterSetterImpl
    public interface UpdaterSetterImpl {
    
        void setUpdaterId(String updaterId);
    
        void setUpdaterName(String updaterName);
    
        void setUpdateTime(Date updateTime);
    }
    

    编写拦截器

    
    /**
     * @ClassName: BaseEntityMapperInterceptor
     * @Author: ren
     * @Description:
     * @CreateTIme: 2019/7/8 0008 下午 5:26
     **/
    @Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
    public class BaseEntityMapperInterceptor implements Interceptor, WapperInterface {
    
    
        @Override
        public Object intercept(Invocation invocation) throws Throwable {
    
            //获取代理对象,由于注解的反射,返回的为   确定类型 StatementHandler 的实例对象
            StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
    
            //通过包装类,把statementHandler包装成一个可以调用反射的代理对象
            MetaObject metaObject = MetaObject.forObject(statementHandler, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY, DEFAULT_REFLECTOR_FACTORY);
    
            //事实上拦截到的时RoutingStatementHandler,需要调用其中的 delegate 属性,才可以调用到  mappedStatement,然后通过反射调用获取到mappedStatement对象
            MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
    
            DefaultParameterHandler parameterHandler = (DefaultParameterHandler) metaObject.getValue("delegate.parameterHandler");
    
            //获取查询映射的名称
            String id = mappedStatement.getId();
            String methodName = id.substring(id.lastIndexOf(".") + 1);
    
            Log4jUtils.getInstance(getClass()).debug("进行通用拦截:" + methodName);
            Object parameter = parameterHandler.getParameterObject();
    
            if (methodName.matches("save.*")) {
                // 配置通用变量
                initSaveMethod(parameter);
                if (parameter instanceof HashMap) {
    
                    HashMap map = (HashMap) parameter;
    
                    map.forEach((k, v) -> {
                        if (v instanceof Collection) {
                            Collection collection = (Collection) v;
    
                            collection.forEach(obj -> {
                                // 配置通用变量
                                initSaveMethod(obj);
                            });
                        }
                    });
    
                }
            } else if (methodName.matches("update.*")) {
    
                initUpdateMethod(parameter);
                if (parameter instanceof HashMap) {
                    HashMap map = (HashMap) parameter;
    
                    map.forEach((k, v) -> {
                        if (v instanceof Collection) {
                            Collection collection = (Collection) v;
    
                            collection.forEach(obj -> {
                                // 配置通用变量
                                initUpdateMethod(obj);
                            });
                        }
                    });
                }
    
    
            }
    
            return invocation.proceed();
        }
    
        /**
         * 配置通用更新方法
         *
         * @param parameter
         */
        private void initUpdateMethod(Object parameter) {
            if (parameter instanceof UpdaterSetterImpl) {
                UserEntity user = UserContext.getUserEntity();
                if (null != user) {
                    UpdaterSetterImpl setter = (UpdaterSetterImpl) parameter;
                    setter.setUpdaterId(user.getUserId());
                    setter.setUpdaterName(user.getUsername());
                    setter.setUpdateTime(new Date());
                }
            }
        }
    
        /**
         * 配置通用新增方法
         *
         * @param parameter
         */
        private void initSaveMethod(Object parameter) {
            if (parameter instanceof BaseEntity) {
                Log4jUtils.getInstance(getClass()).debug("配置通用持久化变量");
    
                BaseEntity baseEntity = (BaseEntity) parameter;
                baseEntity.setId(IdWorker.getIdStr());
                baseEntity.setIsDeleted(0);
                baseEntity.setCreateTime(new Date());
            }
    
            if (parameter instanceof CreatorSetterImpl) {
                Log4jUtils.getInstance(getClass()).debug("配置创建人信息");
                UserEntity user = UserContext.getUserEntity();
                if (null != user) {
                    CreatorSetterImpl setter = (CreatorSetterImpl) parameter;
                    setter.setCreatorId(user.getUserId());
                    setter.setCreatorName(user.getUsername());
                }
            }
        }
    
    
        @Override
        public Object plugin(Object target) {
            return Plugin.wrap(target, this);
        }
    
        @Override
        public void setProperties(Properties properties) {
    
        }
    }
    
    在Myabtis配置中加入拦截器
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
    
    <configuration>
        <!--配置全局变量 -->
        <settings>
            <!-- jdbc用getGeneratedKeys 获取数据库自增键值 -->
            <setting name="useGeneratedKeys" value="true" />
            <!-- 使用列别名替代列名 select name as title from table -->
            <setting name="useColumnLabel" value="true" />
            <!-- 开启驼峰命名法: Table(create_time) ->createTime -->
            <setting name="mapUnderscoreToCamelCase" value="true" />
        </settings>
    
        <plugins>
            <plugin interceptor="com.example.oldguy.modules.commons.interceptors.BaseEntityMapperInterceptor"/>
            <!--<plugin interceptor="com.example.oldguy.modules.commons.interceptors.BaseEntityInterceptor"/>-->
            <plugin interceptor="com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor"/>
        </plugins>
    
    </configuration>
    

    相关文章

      网友评论

        本文标题:Mybatis自定义拦截器,处理通用接口

        本文链接:https://www.haomeiwen.com/subject/qwslkctx.html