Mybatis拦截器

Posted 终会飞翔

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mybatis拦截器相关的知识,希望对你有一定的参考价值。

1.介绍 : 

  我自己理解中的mybatis拦截器,和普通拦截器一样,在执行一段程序之前对其做一些特殊处理,网上一般都是用其做分页处理、日志记录...,实现原理就是在预处理前对其进行一些处理

2.简单说明:

  mybatis提供了一个Interceptor接口,方便扩展所需的操作

  Object intercept(Invocation invocation)

  Object plugin(Object target)

  void setProperties(Properties properties)

  我们所需实现的便是以上的三个方法,先对每个方法有个大致了解

  2.1 先说setProperties方法,我们在mybatis.xml配置文件中有一个plugins标签,其中的一个plugin标签对应着一个Interceptor实现类。在plugin标签下,含有property标签用于存放一些我们可修改的配置信息

    举个例子,mysql、sqlServer、oracle他们sql分页的语句都有一定的区别,所以为了区分,我们便可以使用此配置(这个不是重点,其他两个才是)

  2.2 plugin决定我们是否要拦截,拦截条件是什么,返回的是一个什么样的对象

  2.3 intercept方法就是拦截期间我们所做的操作

3.实现过程 :

  3.1 首先封装一个分页数据对象,最少3个参数(页码、每页记录数、起始记录数(算出来的))

  3.2 创建一个实现Interceptor接口的对象,添加注解@Intercepts和@Signature,这里有两个重点

    3.2.1 我们如何使用这两个注解?

      @Signature注解信息更加具体,相当于集合的一个元素,@Intercepts就相当于集合了

      @Signature包含三个参数:(这样就具体的定位了)

        method : 表示拦截的方法

        type :表示拦截的类,Executor、StatementHandler、ParameterHandler和ResultSetHandler这四个接口的实现类

        args:表示方法参数

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

                @Signature(method = "prepare", type = StatementHandler.class, args = {Connection.class}) })  

    3.2.2 如何读取注解信息?

       上文说到plugin指定在什么地方拦截,那么此方法就需要识别这两个注解。当然提供两个注解的是Mybatis,那么mybatis肯定也有解析这两个注解的类,

       Plugin里面有一个静态方法wrap(Object target,Interceptor interceptor)。所以一般plugin里面只要写Plugin.wrap(target,this);就可以了

  3.3 忘了说一点,我们setProperties是最先执行的,所以我们需要预先定义变量来保存配置参数

  3.4 已经拦截了,那么我们先获取当前拦截类,读取拦截类信息,再进行下一步操作(具体案例来分析)

利用拦截器实现Mybatis分页的原理: 
 * 要利用JDBC对数据库进行操作就必须要有一个对应的Statement对象,Mybatis在执行Sql语句前就会产生一个包含Sql语句的Statement对象,而且对应的Sql语句 
 * 是在Statement之前产生的,所以我们就可以在它生成Statement之前对用来生成Statement的Sql语句下手。在Mybatis中Statement语句是通过RoutingStatementHandler对象的 
 * prepare方法生成的。所以利用拦截器实现Mybatis分页的一个思路就是拦截StatementHandler接口的prepare方法,然后在拦截器方法中把Sql语句改成对应的分页查询Sql语句,之后再调用 
 * StatementHandler对象的prepare方法,即调用invocation.proceed()。 
    //对于StatementHandler其实只有两个实现类,一个是RoutingStatementHandler,另一个是抽象类BaseStatementHandler,  
       //BaseStatementHandler有三个子类,分别是SimpleStatementHandler,PreparedStatementHandler和CallableStatementHandler,  
       //SimpleStatementHandler是用于处理Statement的,PreparedStatementHandler是处理PreparedStatement的,而CallableStatementHandler是  
       //处理CallableStatement的。Mybatis在进行Sql语句处理的时候都是建立的RoutingStatementHandler,而在RoutingStatementHandler里面拥有一个  
       //StatementHandler类型的delegate属性,RoutingStatementHandler会依据Statement的不同建立对应的BaseStatementHandler,即SimpleStatementHandler、  
       //PreparedStatementHandler或CallableStatementHandler,在RoutingStatementHandler里面所有StatementHandler接口方法的实现都是调用的delegate对应的方法。  
       //我们在PageInterceptor类上已经用@Signature标记了该Interceptor只拦截StatementHandler接口的prepare方法,又因为Mybatis只有在建立RoutingStatementHandler的时候  
       //是通过Interceptor的plugin方法进行包裹的,所以我们这里拦截到的目标对象肯定是RoutingStatementHandler对象。

    上述内容都来自于 http://elim.iteye.com/blog/1851081?page=2#comments (详细请观看这个博客)

    3.4.1 RoutingStatementHandler handler = (RoutingStatementHandler) invocation.getTarget();//用来获取当前拦截类

    拦截之后我们需要知道接下来该做什么,这又是另一个话题了,这里说个题外话,我觉得MySql可能并不太需要这部分的处理,limit函数友好的帮我们处理了这一类问题

                                    @——@以上信息纯属胡说八道


以上是关于Mybatis拦截器的主要内容,如果未能解决你的问题,请参考以下文章

Mybatis自定义拦截器与插件开发

MyBatis源码分析六MyBatis Plugins(拦截器)

MyBatis源码分析六MyBatis Plugins(拦截器)

Mybatis——拦截器Interceptor

#私藏项目实操分享# Mybatis自定义拦截器与插件开发

mybatis分页插件,自动生成代码插件