• MyBatis Interceptor


    MyBatis的拦截器可以用于在以下对象及方法中拦截修改:

    • Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
    • ParameterHandler (getParameterObject, setParameters)
    • ResultSetHandler (handleResultSets, handleOutputParameters)
    • StatementHandler (prepare, parameterize, batch, update, query)

    每一个方法会对应不同的参数列表, 这些需要体现在Intercepts的Signature中

    配置

    除了实现Interceptor接口以外, 需要在项目中做以下配置

    application.yml

    增加对应的mybatis-config.xml, 因为现在还不支持在yml中配置plugin

    mybatis:
      type-aliases-package: com.compayn.proj.commons.api.dto
      mapper-locations: classpath:mapper/*.xml
      config-location: classpath:mybatis-config.xml
    

    mybatis-config.xml

    增加mybatis配置文件, 注意这里配置的拦截器, 其实际执行顺序是自下而上的

    <?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>
            <setting name="..." value="true" />
        </settings>
    
        <plugins>
            <!-- The invocation order is bottom up -->
            <plugin interceptor="com.company.proj.commons.impl.interceptor.BaseInterceptor" />
        </plugins>
    
    </configuration>
    

      

    Interceptor实现

    一个简单的拦截器实现, 可以输出执行的sql, 以及执行时间.

    import org.apache.ibatis.executor.Executor;
    import org.apache.ibatis.executor.statement.StatementHandler;
    import org.apache.ibatis.mapping.BoundSql;
    import org.apache.ibatis.mapping.MappedStatement;
    import org.apache.ibatis.plugin.Interceptor;
    import org.apache.ibatis.plugin.Intercepts;
    import org.apache.ibatis.plugin.Invocation;
    import org.apache.ibatis.plugin.Plugin;
    import org.apache.ibatis.plugin.Signature;
    import org.apache.ibatis.session.ResultHandler;
    import org.apache.ibatis.session.RowBounds;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import java.sql.Statement;
    import java.util.Properties;
    
    @Intercepts({
            @Signature(type = StatementHandler.class, method = "batch", args = { Statement.class}),
            @Signature(type = StatementHandler.class, method = "update", args = { Statement.class}),
            @Signature(type = StatementHandler.class, method = "query", args = { Statement.class, ResultHandler.class}),
            @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
            @Signature(type = Executor.class, method = "update", args = {MappedStatement.class,Object.class})})
    public class BaseInterceptor implements Interceptor {
        private static Logger logger = LoggerFactory.getLogger(BaseInterceptor.class);
    
        /**
         * 用于封装目标对象, 可以返回目标对象本身也可以返回一个它的代理, 这将决定是否会进行拦截
         */
        @Override
        public Object plugin(Object target) {
            if (target instanceof Executor) { // 仅当对象为Executor时, 才使用本插件
                return Plugin.wrap(target, this);
            } else {
                return target;
            }
        }
    
        /**
         * 用于配置本插件的相关属性
         */
        @Override
        public void setProperties(Properties properties) {
            // Do nothing
        }
    
        @Override
        public Object intercept(Invocation invocation) throws Throwable {
            long start = System.currentTimeMillis();
    
            Object target = invocation.getTarget(); //被代理对象
    
            if (target instanceof Executor) {
                MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
                Object parameter = invocation.getArgs()[1];
                BoundSql boundSql = mappedStatement.getBoundSql(parameter);
                String sql = boundSql.getSql();
                logger.info("SQL: {}", sql);
            }
    
            Object result = invocation.proceed();
            long duration = System.currentTimeMillis() - start;
            logger.info("Time elapsed: {}ms", duration);
            return result;
        }
    }
    

    代码说明

    @Intercepts 注解: 这个地方配置需要拦截的对象方法, 每个方法对应一个Signature, 这个Signature由对象类型, 方法名和参数组成, 方法名和参数可以直接参考这个对象的接口.

    Object plugin(Object target)接口: 用于封装目标对象, 可以返回目标对象本身也可以返回一个它的代理, 这将决定是否会进行拦截

    void setProperties(Properties properties)接口: 用于配置本插件的相关属性, 值可以通过Mybatis配置文件传入

    Object intercept(Invocation invocation) throws Throwable接口: 执行拦截的方法, 其中 invocation.getTarget() 可以看到实际被代理的对象, 根据对象类型不同, 可以读取这个对象方法的参数并进行需要的操作.

  • 相关阅读:
    c数据结构 -- 线性表之 顺序存储结构 于 链式存储结构 (单链表)
    c数据结构 绪论
    c数据结构 -- 使用链表实现计数
    c数据结构 -- 链表的理解
    vue mvvm原理与简单实现 -- 上篇
    vue图书小案例
    排序
    裁剪图片
    下载图片
    图片缩放
  • 原文地址:https://www.cnblogs.com/milton/p/12746436.html
Copyright © 2020-2023  润新知