话不多说上代码
这是自定义的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)