Mybatis Plugin(拦截器)的开发

1.Plugin

MyBatis 允许使用插件来拦截的方法调用包括:

• Executor (update, query, flushStatements, commit, rollback,

getTransaction, close, isClosed)

• ParameterHandler (getParameterObject, setParameters)

• ResultSetHandler (handleResultSets, handleOutputParameters)

• StatementHandler (prepare, parameterize, batch, update, query)

注意;可以通过插件拦截到这四个对象,修改参数等操作:

你必须要知道的类:

  1. org.apache.ibatis.plugin.Plugin
  2. org.apache.ibatis.reflection.SystemMetaObject

2.使用步骤

    1. 实现 Interceptor 接口
      1. 三个方法执行顺序
        1. setProperties()
        2. plugin()
        3. intercept()
 1 FirstIntercepter=====>setProperties
 2 FirstIntercepter====>[email protected]
 3 FirstIntercepter====>plu[email protected]2f0a87b3
 4 FirstIntercepter====>plu[email protected]4fcd19b3
 5 FirstIntercepter====>plu[email protected]2fd66ad3
 6 DEBUG 09-05 11:56:24,696 ==> Preparing: select * from employee where id=? (BaseJdbcLogger.java:159)
 7 FirstIntercepter:===>intercept
 8 DEBUG 09-05 11:56:24,722 ==> Parameters: 1(Integer) (BaseJdbcLogger.java:159)
 9 DEBUG 09-05 11:56:24,739 <== Total: 1 (BaseJdbcLogger.java:159)
10 Employee [id=1, lastName=tom, gender=1, email[email protected], depid=null]
    1. 给你的拦截器签名:
 1 /**
 2 * 完成插件签名:
 3 * 告诉MyBatis当前插件用来拦截哪个对象的哪个方法
 4 * type:要拦截的四大类型
 5 * method:拦截那个方法
 6 * args:这个方法的入参
 7 * */
 8 @Intercepts({
 9 @Signature(type=StatementHandler.class,
10 method="parameterize",
11 args=java.sql.Statement.class
12 )
13 })
14 public class FirstIntercepter implements Interceptor
    1. mybatis-cfg.xml中配置插件
      1. 这里注意配置plugins的标签顺序,以免出错,在environments上面
<!-- plugins 插件的配置 实际上是使用:intercepter原理代理的 -->
<plugins>
<plugin interceptor="mybatis.intercepter.FirstIntercepter">
<property name="param1" value="root"/>
<property name="param2" value="root"/>
</plugin>
</plugins>

3.多个插件的执行

  1. 、多个插件依次生成目标对象的代理对象,层层包裹,先声明的先包裹;形成代理链
  2. 、可以理解为:初始化执行
  3. 执行log
  4. FirstIntercepter=====>setProperties
 1 MySecondIntercepter====>setProperties:{param1=root}
 2 FirstIntercepter====>[email protected]
 3 MySecondIntercepter====>plugin:[email protected]
 4 FirstIntercepter====>plu[email protected]2f0a87b3
 5 MySecondIntercepter====>plugin:[email protected]a87b3
 6 FirstIntercepter====>plu[email protected]4fcd19b3
 7 MySecondIntercepter====>plugin:[email protected]d19b3
 8 FirstIntercepter====>plu[email protected]2fd66ad3
 9 MySecondIntercepter====>plugin:[email protected]66ad3
10 DEBUG 09-05 12:07:01,928 ==> Preparing: select * from employee where id=? (BaseJdbcLogger.java:159)
11 MySecondIntercepter====>intercept:public abstract void org.apache.ibatis.executor.statement.StatementHandler.parameterize(java.sql.Statement) throws java.sql.SQLException
12 FirstIntercepter:===>intercept
13 DEBUG 09-05 12:07:01,954 ==> Parameters: 1(Integer) (BaseJdbcLogger.java:159)
14 DEBUG 09-05 12:07:01,968 <== Total: 1 (BaseJdbcLogger.java:159)
15 Employee [id=1, lastName=tom, gender=1, email[email protected], depid=null]

4.实现拦截修改参数

  • sql
<!-- Employee getSelectEmp(Integer id); -->
<select id="getSelectEmp" parameterType="java.lang.Integer"
resultType="mybatis.bean.Employee">
select * from employee where id=#{id}
</select>
  • 这里我们拦截id:

由于ibatis中参数的声明存在与 StatementHandler中所以注意签名

  • 1 @Intercepts({
    2 @Signature(type=StatementHandler.class,
    3 method="parameterize",
    4 args=java.sql.Statement.class
    5 )
    6 })

    业务逻辑intercept方法中

 1 /**
 2 * 1:业务逻辑处理的方法:
 3 */
 4 @Override
 5 public Object intercept(Invocation invocation) throws Throwable {
 6 //在这里可以进行业务逻辑修改
 7 System.out.println("FirstIntercepter:===>intercept"+invocation.getMethod());
 8
 9 MetaObject metaObject = SystemMetaObject.forObject(invocation.getTarget());
10 //拿到target的元数据 StatementHandler==>ParameterHandler===>
11 //DefaultParameterHandler==>>parameterObject
12 Object value = metaObject.getValue("parameterHandler.parameterObject");
13 System.out.println("sql "+value.toString());
14 //修改完sql语句要用的参数
15 metaObject.setValue("parameterHandler.parameterObject", 2);
16 Object object = invocation.proceed();
17 return object;
18 }
  • 打印log,
    • 可以看到原来入参为1,现在经过拦截器修改入参为2
1 DEBUG 09-05 12:36:23,387 ==> Preparing: select * from employee where id=? (BaseJdbcLogger.java:159)
2 MySecondIntercepter====>intercept:public abstract void org.apache.ibatis.executor.statement.StatementHandler.parameterize(java.sql.Statement) throws java.sql.SQLException
3 FirstIntercepter:===>interceptpublic abstract void org.apache.ibatis.executor.statement.StatementHandler.parameterize(java.sql.Statement) throws java.sql.SQLException
4 sql 1
5 DEBUG 09-05 12:36:23,418 ==> Parameters: 2(Integer) (BaseJdbcLogger.java:159)
6 DEBUG 09-05 12:36:23,432 <== Total: 1 (BaseJdbcLogger.java:159)
7 Employee [id=2, lastName=cat, gender=0, email[email protected], depid=null]

原文地址:https://www.cnblogs.com/dgwblog/p/9591499.html

时间: 2024-11-05 21:58:32

Mybatis Plugin(拦截器)的开发的相关文章

Mybatis Interceptor 拦截器原理 源码分析

Mybatis采用责任链模式,通过动态代理组织多个拦截器(插件),通过这些拦截器可以改变Mybatis的默认行为(诸如SQL重写之类的),由于插件会深入到Mybatis的核心,因此在编写自己的插件前最好了解下它的原理,以便写出安全高效的插件. 代理链的生成 Mybatis支持对Executor.StatementHandler.PameterHandler和ResultSetHandler进行拦截,也就是说会对这4种对象进行代理. 通过查看Configuration类的源代码我们可以看到,每次都

spring mvc 配置 mybatis sql拦截器

直接上代码: mybatis配置中 添加  <property name="plugins"> 如下: <bean id="sqlSessionFactory" class="com.hotent.core.mybatis.SqlSessionFactoryFactoryBean"> <property name="configLocation" value="classpath:/co

Mybatis之拦截器--获取执行SQL实现多客户端数据同步

最近的一个项目是将J2EE环境打包安装在客户端(使用 nwjs + NSIS 制作安装包)运行, 所有的业务操作在客户端完成, 数据存储在客户端数据库中. 服务器端数据库汇总各客户端的数据进行分析. 其中客户端ORM使用Mybatis. 通过Mybatis拦截器获取所有在执行的SQL语句, 定期同步至服务器. 本文通过在客户端拦截SQL的操作介绍Mybatis拦截器的使用方法. 1. 项目需求 客户分店较多且比较分散, 部分店内网络不稳定, 客户要求每个分店在无网络的情况下也能正常使用系统, 同

mybatis - 基于拦截器修改执行中的SQL语句

拦截器介绍 mybatis提供了@Intercepts注解允许开发者对mybatis的执行器Executor进行拦截. Executor接口方法主要有update.query.commit.rollback等等. 主要思路为: 进入拦截器方法中 获取拦截器方法参数 获取解析参数及SQL 自定义生成自己的SQL语句 将自定义SQL设置进参数中 由mybatis处理后续问题 拦截器代码 import org.apache.ibatis.cache.CacheKey; import org.apach

MyBatis之拦截器分页

鲁春利的工作笔记,好记性不如烂笔头 数据库的分页主要有物理分页和逻辑分页.    物理分页:数据库本身提供的分页方式,如MySQL的limit.Oracle的rownum.SqlServer的top,好处是效率高,不好的地方就是不同数据库有不同的查询方式.    逻辑分页:从数据库将所有记录查询出来,存储到内存中,然后数据再直接从内存中获取并筛选分页,好处是能够统一查询方式,不好的地方是效率低,因为每次都要把全部数据查询出来再处理. 常用orm框架采用的分页技术:①:hibernate采用的是物

mybatis使用拦截器显示sql,使用druid配置连接信息

a:focus { outline: thin dotted #333; outline: 5px auto -webkit-focus-ring-color; outline-offset: -2px; } a:hover { outline: 0; } a:active { outline: 0; } a:hover { color: #005580 !important; text-decoration: underline !important; } blockquote small:b

Mybatis那些事-拦截器(Plugin+Interceptor)

作者:yhjyumi的专栏 Mybatis的拦截器实现机制,使用的是JDK的InvocationHandler. 当我们调用ParameterHandler,ResultSetHandler,StatementHandler,Executor的对象的时候,实际上使用的是Plugin这个代理类的对象,这个类实现了InvocationHandler接口.接下来我们就知道了,在调用上述被代理类的方法的时候,就会执行Plugin的invoke方法.Plugin在invoke方法中根据@Intercept

mybatis Spring MVC添加分页拦截器

网上有很多封装的mybatis 分页拦截器,但是看起来都比较乱,不能直接套用,在这里贴出项目中的分页源码出来供大家参考. Controller 层: @RequestMapping("/channelList") public String channelList(HttpServletRequest request,AppMarket appMarket,Model model){ String pageNo = request.getParameter("pageNo&q

由浅入深分析mybatis通过动态代理实现拦截器(插件)的原理

最近在用mybatis做项目,需要用到mybatis的拦截器功能,就顺便把mybatis的拦截器源码大致的看了一遍,为了温故而知新,在此就按照自己的理解由浅入深的理解一下它的设计. 和大家分享一下,不足和谬误之处欢迎交流.直接入正题. 首先,先不管mybatis的源码是怎么设计的,先假设一下自己要做一个拦截器应该怎么做.拦截器的实现都是基于代理的设计模式设计的,简单的说就是要创造一个目标类的代理类,在代理类中执行目标类的方法并拦截执行拦截器代码. 那么我们就用JDK的动态代理设计一个简单的拦截器

mybatis拦截器使用

[toc] mybatis拦截器入门 mybatis 拦截器接口Interceptor Interceptor接口,我们通过这个接口可以自定义我们自己的拦截器,从而实现在拦截的时候写上我们自己的一些逻辑.该接口提供了三个方法, 接口介绍: intercept方法: intercept方法是在进行拦截的时候要执行的方法. plugin方法: 该方法是拦截器用于封装目标对象的,通过该方法我们可以返回目标对象本身,也可以返回一个它的代理. setProperties方法: mybatis配置文件中co