自定义Mybatis拦截器 与PageHelper插件冲突问题

话不多说上代码

这是自定义的mybatis插件拦截器,用来截取查询的sql


@Slf4j
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class ExamplePlugin implements Interceptor {

    /**
     * 进行拦截的时候要执行的方法
     * @param invocation
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        System.out.println("====intercept======");

        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        BoundSql boundSql = statementHandler.getBoundSql();
        //获取到原始sql语句
        String sql = boundSql.getSql();
        log.info(sql);
        DataSourceContextHolder.setDB(sql);
        Object proceed = invocation.proceed();
        return proceed;

    }

    @Override
    public Object plugin(Object target) {
        System.out.println("-----------------------------plugin-------------------------");
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
        System.out.println("====setProperties======");
    }

}

如果项目没有使用PageHelper,该拦截器是正常能拦截,并且能实现sql修改,sql记录,抓取sql的功能

但是项目一但使用了PageHelper 该拦截器会失效
原因分析:
com.github.pagehelper.PageInterceptor#intercept

拦截器是责任链的形式一半结束时候会往下传递invocation.proceed();
通过分析,发现拦截器与pagehelper定义分页拦截器有冲突,分页拦截器先调用,他在调用完成后没有往下调,
所以自定义拦截器不生效

解决方案:
思路:想办法吧myInterceptor 弄到pageInterceptor的后面去。
1.让自定义的拦截器不交由spring管理,在项目启动的时候自己new一个,添加到拦截器链的最后面

/**
 * mybatis拦截器配置
 * @author alan
 */
@Configuration
public class MybatisInterceptorAutoConfiguration {

    @Autowired
    private List<SqlSessionFactory> sqlSessionFactoryList;

    /**
     * 只会执行一次
     * 顺序:Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法)
     */
    @PostConstruct
    public void addMysqlInterceptor() {
        //创建自定义mybatis拦截器,添加到chain的最后面
        ExamplePlugin mybatisInterceptor = new ExamplePlugin();
        for (SqlSessionFactory sqlSessionFactory : sqlSessionFactoryList) {
            org.apache.ibatis.session.Configuration configuration = sqlSessionFactory.getConfiguration();
            //自己添加
            configuration.addInterceptor(mybatisInterceptor);
        }
    }
}

注意
需要拦截器拦截的是同一个目标方法,chain中拦截器执行顺序才会生效
比如myInterceptor 和pageInterceptor 拦截的都是拦截Excutor的query方法,可以生效
对象执行顺序如下(先—》后) (不受拦截器在chain中顺序控制)
1.Executor
(update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
2.ParameterHandler
(getParameterObject, setParameters)
3.StatementHandler
(prepare, parameterize, batch, update, query)
4.ResultSetHandler
(handleResultSets, handleOutputParameters)

你可能感兴趣的:(java)