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

前言
相信大家对拦截器并不陌生,对也不陌生 。
有用过的,那么对拦截器也不陌生了,按照使用的规则触发sql拦截,帮我们自动添加分页参数。
那么今天,我们的实践 自定义拦截器也是如此,本篇文章实践的效果:
针对一些使用 单个实体类去接收返回结果的 方法,我们拦截检测,如果没写 LIMIT 1 ,我们将自动帮忙填充,达到查找单条数据 效率优化的效果 。
ps: 当然,跟着该篇学会了这个之后,那么可以扩展的东西就多了,大家按照自己的想法或是项目需求都可以自己发挥 。我该篇的实践仅仅作为抛砖引玉吧 。
正文
实践的准备 :
整合 ,然后故意写了3个查询方法,1个是list 列表数据,2个是 单条数据。
我们通过自己写一个实现 框架的来做文章:
.java :
import org.apache.ibatis.executor.Executor;import org.apache.ibatis.mapping.*;import org.apache.ibatis.plugin.*;import org.apache.ibatis.session.ResultHandler;import org.apache.ibatis.session.RowBounds;import org.springframework.stereotype.Component;import java.lang.reflect.Method;import java.util.*;/*** @Author JCccc* @Description* @Date 2021/12/14 16:56*/@Component@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})public class MybatisInterceptor implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {//获取执行参数Object[] objects = invocation.getArgs();MappedStatement ms = (MappedStatement) objects[0];//解析执行sql的map方法,开始自定义规则匹配逻辑String mapperMethodAllName = ms.getId();int lastIndex = mapperMethodAllName.lastIndexOf(".");String mapperClassStr = mapperMethodAllName.substring(0, lastIndex);String mapperClassMethodStr = mapperMethodAllName.substring((lastIndex + 1));Class mapperClass = Class.forName(mapperClassStr);Method[] methods = mapperClass.getMethods();Class returnType;for (Method method : methods) {if (method.getName().equals(mapperClassMethodStr)) {returnType = method.getReturnType();if (returnType.isAssignableFrom(List.class)) {System.out.println("返回类型是 List");System.out.println("针对List 做一些操作");} else if (returnType.isAssignableFrom(Set.class)) {System.out.println("返回类型是 Set");System.out.println("针对Set 做一些操作");} else{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);}}}}//继续执行逻辑return invocation.proceed();}@Overridepublic Object plugin(Object o) {//获取代理权if (o instanceof Executor) {//如果是Executor(执行增删改查操作),则拦截下来return Plugin.wrap(o, this);} else {return o;}}/*** 定义一个内部辅助类,作用是包装 SQL*/class MyBoundSqlSqlSource implements SqlSource {private BoundSql boundSql;public MyBoundSqlSqlSource(BoundSql boundSql) {this.boundSql = boundSql;}@Overridepublic BoundSql getBoundSql(Object parameterObject) {return boundSql;}}private MappedStatement newMappedStatement(MappedStatement ms, SqlSource newSqlSource) {MappedStatement.Builder builder = newMappedStatement.Builder(ms.getConfiguration(), ms.getId(), newSqlSource, ms.getSqlCommandType());builder.resource(ms.getResource());builder.fetchSize(ms.getFetchSize());builder.statementType(ms.getStatementType());builder.keyGenerator(ms.getKeyGenerator());if (ms.getKeyProperties() != null && ms.getKeyProperties().length > 0) {builder.keyProperty(ms.getKeyProperties()[0]);}builder.timeout(ms.getTimeout());builder.parameterMap(ms.getParameterMap());builder.resultMaps(ms.getResultMaps());builder.resultSetType(ms.getResultSetType());builder.cache(ms.getCache());builder.flushCacheRequired(ms.isFlushCacheRequired());builder.useCache(ms.isUseCache());return builder.build();}@Overridepublic void setProperties(Properties properties) {//读取mybatis配置文件中属性}}