MyBatis提供了一种插件(plugin)的功能,虽然叫做插件,其实就是拦截器功能

MyBatis 允许拦截的接口

MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:

  1. Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
  2. ParameterHandler (getParameterObject, setParameters)
  3. ResultSetHandler (handleResultSets, handleOutputParameters)
  4. StatementHandler (prepare, parameterize, batch, update, query)

Executor接口的部分方法,比如update,query,commit,rollback等方法,还有其他接口的一些方法等。

总体概括为:

  1. 拦截执行器的方法
  2. 拦截参数的处理
  3. 拦截结果集的处理,为sql执行之后的结果拦截过滤
  4. 拦截Sql语法构建的处理,为sql执行之前的拦截进行sql封装

MyBatis拦截器的接口定义

一共有三个方法interceptpluginsetProperties

setProperties()

方法主要是用来从配置中获取属性。

如果是使用xml式配置拦截器,可在Mybatis配置文件中添加如下节点,属性可以以如下方式传递

<plugins><plugin interceptor="tk.mybatis.simple.plugin.XXXInterceptor"><property name="propl" value="valuel" /><property name="prop2" value="value2" /></plugin>
</plugins>

如果在Spring boot中使用,则需要单独写一个配置类,如下:

@Configuration
public class MybatisInterceptorConfig {@Beanpublic String myInterceptor(SqlSessionFactory sqlSessionFactory) {ExecutorInterceptor executorInterceptor = new ExecutorInterceptor();Properties properties = new Properties();properties.setProperty("prop1","value1");executorInterceptor.setProperties(properties);return "interceptor";}
}

如果说不需要配置属性,则在spring boot中,不需要去编写配置类,只需要像我一样在拦截器上加个@Component即可。

plugin()

方法用于指定哪些方法可以被此拦截器拦截。

intercept()

方法是用来对拦截的sql进行具体的操作。

注解实现

MyBatis拦截器用到了两个注解:@Intercepts@Signature

@Intercepts({@Signature(type = Executor.class, method = "query",args = {MappedStatement.class, Object.class,RowBounds.class, ResultHandler.class}),@Signature(type = Executor.class, method = "query",args = {MappedStatement.class, Object.class, RowBounds.class,ResultHandler.class, CacheKey.class, BoundSql.class}),}
)

type的值与类名相同,method方法名相同,为了避免方法重载,args中指定了各个参数的类型和个数,可通过invocation.getArgs()获取参数数组。

Executor 拦截器实现

@Intercepts({@Signature(type= Executor.class,method = "query",args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})
})
@Slf4j
@Component
public class ExecutorInterceptor implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {String sql = ExecutorPluginUtils.getSqlByInvocation(invocation);//可以对sql重写log.error("拦截器ExecutorInterceptor:"+sql);//sql = "SELECT id from BUS_RECEIVER where id = ? ";ExecutorPluginUtils.resetSql2Invocation( invocation,  sql);return invocation.proceed();}@Overridepublic Object plugin(Object o) {return Plugin.wrap(o, this);}@Overridepublic void setProperties(Properties properties) {}}

ParameterHandler 拦截器实现

/*** @Author: ynz* @Date: 2018/12/23/023 12:07*/
@Intercepts({@Signature(type = ParameterHandler.class, method = "setParameters", args = PreparedStatement.class),
})
@Component
@Slf4j
public class ParamInterceptor  implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {log.error("拦截器ParamInterceptor");//拦截 ParameterHandler 的 setParameters 方法 动态设置参数if (invocation.getTarget() instanceof ParameterHandler) {ParameterHandler parameterHandler = (ParameterHandler) invocation.getTarget();PreparedStatement ps = (PreparedStatement) invocation.getArgs()[0];// 反射获取 BoundSql 对象,此对象包含生成的sql和sql的参数map映射Field boundSqlField = parameterHandler.getClass().getDeclaredField("boundSql");boundSqlField.setAccessible(true);BoundSql boundSql = (BoundSql) boundSqlField.get(parameterHandler);// 反射获取 参数对像Field parameterField = parameterHandler.getClass().getDeclaredField("parameterObject");parameterField.setAccessible(true);Object parameterObject = parameterField.get(parameterHandler);if (parameterObject instanceof Map) {//将参数中的name值改为2((Map) parameterObject).put("name","2");}// 改写的参数设置到原parameterHandler对象parameterField.set(parameterHandler, parameterObject);parameterHandler.setParameters(ps);log.error(JSON.toJSONString(boundSql.getParameterMappings()));log.error(JSON.toJSONString(parameterObject));}return invocation.proceed();}@Overridepublic Object plugin(Object o) {return Plugin.wrap(o, this);}@Overridepublic void setProperties(Properties properties) {}
}

ResultSetHandler 拦截器实现

@Intercepts({@Signature(type = ResultSetHandler.class, method = "handleResultSets", args={Statement.class})
})
@Component
@Slf4j
public class ResultInterceptor implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {log.error("拦截器ResultInterceptor");// ResultSetHandler resultSetHandler1 = (ResultSetHandler) invocation.getTarget();//通过java反射获得mappedStatement属性值//可以获得mybatis里的resultypeObject result = invocation.proceed();if (result instanceof ArrayList) {ArrayList resultList = (ArrayList) result;for (int i = 0; i < resultList.size(); i++) {Object oi = resultList.get(i);Class c = oi.getClass();Class[] types = {String.class};Method method = c.getMethod("setAddress", types);// 调用obj对象的 method 方法method.invoke(oi, "china");}}return result;}@Overridepublic Object plugin(Object target) {return Plugin.wrap(target, this);}@Overridepublic void setProperties(Properties properties) {}
}

StatementHandler 拦截器实现

/*** @Author: ynz* @Date: 2018/12/23/023 14:22*/
@Intercepts({@Signature(type = StatementHandler.class,method = "prepare",args = {Connection.class, Integer.class})})
@Component
@Slf4j
public class StatementInterceptor implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {StatementHandler statementHandler = (StatementHandler) PluginUtils.realTarget(invocation.getTarget());MetaObject metaStatementHandler = SystemMetaObject.forObject(statementHandler);MappedStatement mappedStatement = (MappedStatement) metaStatementHandler.getValue("delegate.mappedStatement");//只拦截select方法if (!SqlCommandType.SELECT.equals(mappedStatement.getSqlCommandType())) {return invocation.proceed();}BoundSql boundSql = (BoundSql) metaStatementHandler.getValue("delegate.boundSql");//获取到sqlString originalSql = boundSql.getSql();//可以对originalSql进行改写log.error("拦截器StatementInterceptor:"+originalSql);metaStatementHandler.setValue("delegate.boundSql.sql", originalSql);Object parameterObject = boundSql.getParameterObject();return invocation.proceed();}@Overridepublic Object plugin(Object target) {return Plugin.wrap(target, this);}@Overridepublic void setProperties(Properties properties) {}
}

Spring Boot整合

方法1:手写一个配置类

@Configuration
public class MybatisInterceptorConfig {@Beanpublic String myInterceptor(SqlSessionFactory sqlSessionFactory) {ExecutorInterceptor executorInterceptor = new ExecutorInterceptor();Properties properties = new Properties();properties.setProperty("prop1","value1");executorInterceptor.setProperties(properties);sqlSessionFactory.getConfiguration().addInterceptor(executorInterceptor);sqlSessionFactory.getConfiguration().addInterceptor(new ParamInterceptor());sqlSessionFactory.getConfiguration().addInterceptor(new ResultInterceptor());return "interceptor";}
}

方法2:在拦截器上加@Component注解

Springboot的Mybatis拦截器实现相关推荐

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

    前言 相信大家对拦截器并不陌生,对mybatis也不陌生. 有用过pagehelper的,那么对mybatis拦截器也不陌生了,按照使用的规则触发sql拦截,帮我们自动添加分页参数 . 那么今天,我们 ...

  2. SpringBoot集成mybatis拦截器的实现

    ①创建SpringBoot工程 项目目录: ②导入jar包 <!--SpringBoot与mybatis的整合--> <dependency><groupId>or ...

  3. 面试官:你能说说MyBatis拦截器原理吗?

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 作者:Format cnblogs.com/fangjian042 ...

  4. mybatis拦截器添加额外参数

    上一篇中讲了mybatis拦截器的实现 这一篇扩展mybatis在拦截器中添加额外参数 在mybatis的mapper.xml文件中,我们可以使用#{}或${}的方式获取到参数,这些参数都需要提前我们 ...

  5. Mybatis拦截器安全加解密MySQL数据实战

    需求背景 公司为了通过一些金融安全指标(政策问题)和防止数据泄漏,需要对用户敏感数据进行加密,所以在公司项目中所有存储了用户信息的数据库都需要进行数据加密改造.包括Mysql.redis.mongod ...

  6. Mybatis拦截器的使用及其源码详解

    Mybatis拦截器的使用及其源码详解 Mybatis相关全览 一.简介 执行与添加顺序 拦截器生效入口 二.使用 例子 三.原理 加载入口 生成代理 遍历拦截器 匹配&生成代理 四.实践例子 ...

  7. MySQL拦截器获取xml id_关于mybatis拦截器,有谁知道怎么对结果集进行拦截,将指定字段查询结果进行格式化...

    用MyBatis结果集拦截器做过这样一个需求: 由于项目需求经常变动,项目MySQL数据库都是存放JSON字符串,例如:用户的基本信息随着版本升级可能会有变动 数据表 CREATE TABLE `ac ...

  8. list mybatis 接收 类型_基于mybatis拦截器实现的一款简易影子表自动切换插件

    近期因工作需要,小编基于mybatis拦截器开发了一款简易影子表自动切换插件,可以根据配置实现动态修改表名,即将对原source table表的操作自动切换到对target table表的操作.该插件 ...

  9. 犯罪心理解读Mybatis拦截器

    原文链接:"犯罪心理"解读Mybatis拦截器 Mybatis拦截器执行过程解析 文章写过之后,我觉得 "Mybatis 拦截器案件"背后一定还隐藏着某种设计动 ...

  10. MyBatis拦截器原理探究MyBatis拦截器原理探究

    MyBatis拦截器介绍 MyBatis提供了一种插件(plugin)的功能,虽然叫做插件,但其实这是拦截器功能.那么拦截器拦截MyBatis中的哪些内容呢? 我们进入官网看一看: MyBatis拦截 ...

最新文章

  1. 基于Tkinter利用python实现颜色空间转换程序
  2. html辅助方法引入验证类后怎么写,Html辅助方法
  3. 使用ABAP(ADBC)和Java(JDBC)连接SAP HANA数据库
  4. 每日程序C语言11-求s=a+aa+aaa+aaaa+aa…a
  5. java并发中的延迟初始化
  6. python 文件遍历
  7. hdu 4970 killing monster 代代相传刷qq 不用线段树啦~
  8. PCB Genesis脚本 C#调用Javascript
  9. 设置checkbox的只读
  10. Windows Phone7成为诺基亚核心目标
  11. YUY2转RGB 的各种版本
  12. easyui-textbox锁定按钮不锁定_刘诗雯锁定世界杯参赛资格!孙颖莎不满足要求,无缘对阵伊藤美诚...
  13. Allavsoft 下载 .m3u8 视频
  14. 六个主要的社会网络分析软件的比较
  15. 短时傅里叶变换程序实现
  16. 我用飞桨做了一个菜品图像识别系统
  17. 《Adobe Photoshop CS6中文版经典教程》目录—导读
  18. 什么是VBA编程语言?
  19. NIO和BIO的比较
  20. Java计算机毕业设计图书馆座位预约管理系统源码+系统+数据库+lw文档

热门文章

  1. ios不能保存png_花瓣网上面的图不能下载?教你怎样快速批量提取花瓣网图片
  2. [境内法规]中国人民银行关于分支行反洗钱工作的指导意见—银发[2005]56号
  3. viper4android ddc,蝰蛇音效v4a音效最新版
  4. Learning multi-level structural information for small organ segmentation
  5. 如何搭建前端开发环境
  6. 【深度学习基本概念】上采样、下采样、卷积、池化
  7. Redis的安装启动,菜鸟使用(windows)
  8. 订单页面添加收货地址html,添加收货地址展示
  9. UNITY游戏制作流程
  10. Python考试题库(含答案)