Springboot 自定义mybatis 拦截器,实现我们要的扩展( 二 )


简单代码端解析:

Springboot 自定义mybatis 拦截器,实现我们要的扩展

文章插图
① 拿出执行参数,里面有很多东西给我们用的,我本篇主要是用 。大家可以发挥自己的想法 。打debug可以自己看看里面的东西 。
//获取执行参数Object[] objects = invocation.getArgs();MappedStatement ms = (MappedStatement) objects[0];
② 这里我主要是使用了从里面拿出来的id,做切割分别切出来 目前执行的sql的是哪个,然后方法是哪个 。
String mapperMethodAllName = ms.getId();int lastIndex = mapperMethodAllName.lastIndexOf(".");String mapperClassStr = mapperMethodAllName.substring(0, lastIndex);String mapperClassMethodStr = mapperMethodAllName.substring((lastIndex + 1));
③ 这就是我自己随便写的一下,我直接根据切割出来的类找出里面的方法,主要是为了拿出每个方法的返回类型,因为 我这篇实践内容就是,判断出单个pojo接受的方法,加个LIMIT 1 ,其他的 LIST 、SET 、 Page 等等这些,我暂时不做扩展 。
Class mapperClass = Class.forName(mapperClassStr);Method[] methods = mapperClass.getMethods();Class returnType;
【Springboot 自定义mybatis 拦截器,实现我们要的扩展】④这一段代码就是该篇的拓展逻辑了,从里面拿出 ,然后再拿出,然后一顿操作 给加上LIMIT 1 ,然后new 一个新的,一顿操作塞回去 里面 。
BoundSql boundSql = ms.getSqlSource().getBoundSql(objects[1]);String oldSql = boundSql.getSql().toLowerCase(Locale.CHINA).replace("[\\t\\n\\r]", " ");if (!oldSql.contains("LIMIT")){String newSql = boundSql.getSql().toLowerCase(Locale.CHINA).replace("[\\t\\n\\r]", " ") + " LIMIT 1";BoundSql newBoundSql = new BoundSql(ms.getConfiguration(), newSql,boundSql.getParameterMappings(), boundSql.getParameterObject());MappedStatement newMs = newMappedStatement(ms, new MyBoundSqlSqlSource(newBoundSql));for (ParameterMapping mapping : boundSql.getParameterMappings()) {String prop = mapping.getProperty();if (boundSql.hasAdditionalParameter(prop)) {newBoundSql.setAdditionalParameter(prop, boundSql.getAdditionalParameter(prop));}}Object[] queryArgs = invocation.getArgs();queryArgs[0] = newMs;System.out.println("打印新SQL语句:" + newSql);}
OK,最后简单来试试效果 :
Springboot 自定义mybatis 拦截器,实现我们要的扩展

文章插图
最后再重申一下,本篇文章内容只是一个抛砖引玉,随便想的一些实践效果,大家可以按照自己的想法发挥 。
最后再补充一个 解决 自定义拦截器和 拦截器 冲突导致失效的问题出现的 解决方案:
加上一个拦截器配置类
.java :
import org.apache.ibatis.session.SqlSessionFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.ApplicationListener;import org.springframework.context.event.ContextRefreshedEvent;import org.springframework.stereotype.Component;import java.util.List;/*** @Author JCccc* @Description* @Date 2021/12/14 16:56*/@Componentpublic class MyDataSourceInterceptorConfig implements ApplicationListener {@Autowiredprivate MybatisInterceptor mybatisInterceptor;@Autowiredprivate List sqlSessionFactories;@Overridepublic void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {for (SqlSessionFactory factory : sqlSessionFactories) {factory.getConfiguration().addInterceptor(mybatisInterceptor);}}}
最后最后再补充多一些,
文中 针对拦截的是 这种接口的插件,
其实 还可以使用、、 。
每当执行这四种接口对象的方法时,就会进入拦截方法,然后我们可以根据不同的插件去拿不同的参数 。
类似:
@Signature(method = "prepare", type = StatementHandler.class, args = {Connection.class,Integer.class})