zoukankan      html  css  js  c++  java
  • 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函数友好的帮我们处理了这一类问题

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

  • 相关阅读:
    使用 Istio 进行 JWT 身份验证(充当 API 网关)
    DNS 私有域的选择:internal.xxx.com/lan.xxx.com 还是 xxx.local/xxx.srv?
    「Bug」K8s 节点的 IP 地址泄漏,导致 IP 被耗尽
    Linux网络学习笔记(二):域名解析(DNS)——以 CoreDNS 为例
    Linux 发行版的选用(服务器和个人桌面)
    「Bug」VMware 虚拟机的关机测试中,Ubuntu 明显比 CentOS 慢
    VMware vSphere :服务器虚拟化
    「Bug」ubuntu 使用国内 apt 源构建 docker 时提示 hash 不匹配
    留言板
    Idea 自定义快捷代码输入 如syso => System.out.println()
  • 原文地址:https://www.cnblogs.com/kongkongFabian/p/9517915.html
Copyright © 2011-2022 走看看