二十六、自定义Mybatis拦截器(1)

1. mybatis分页插件PageHelper实现原理

PageHelper分页的实现是在执行SQL语句之前动态的将分页的SQL拼接进去,从而实现了从数据库中分页查询。

1.1 使用方式

首先回顾一下PageHelper插件的使用方式,非常简单,分2步完成:

第一步:在mybatis的SqlMapConfig.xml配置文件中配置插件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <plugins>
        <!-- com.github.pagehelper 为 PageHelper 类所在包名 -->
        <plugin interceptor="com.github.pagehelper.PageHelper">
            <!-- 设置数据库类型 Oracle,Mysql,MariaDB,SQLite,Hsqldb,PostgreSQL 六种数据库-->
            <property name="dialect" value="mysql"/>
        </plugin>
    </plugins>
</configuration>

第二步:在Java代码中调用插件的API进行分页处理

//分页查询
public PageResult findPage(QueryPageBean queryPageBean) {
  Integer currentPage = queryPageBean.getCurrentPage();
  Integer pageSize = queryPageBean.getPageSize();
  String queryString = queryPageBean.getQueryString();
  
  //分页插件会在执行sql之前将分页关键字追加到SQL后面
  PageHelper.startPage(currentPage,pageSize);
  
  Page<CheckItem> page = checkItemDao.findByCondition(queryString);
  return new PageResult(page.getTotal(),page.getResult());
}

1.2 源码分析(项目启动时执行)

SqlSessionFactoryBuilder:
在这里插入图片描述

XMLConfigBuilder:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Configuration:
在这里插入图片描述

InterceptorChain:

在这里插入图片描述
通过上面的代码,加载了全局配置文件及映射文件同时还将配置的拦截器PageHelper添加到了拦截器链中

上面代码的调用关系如下:
在这里插入图片描述

1.3 源码分析(项目运行中执行)

PageHelper:
在这里插入图片描述

通过上面的代码可以发现,PageHelper插件提供了一个类(PageHelper)实现了Interceptor接口,其本质就是一个拦截器,用于拦截Executor接口的query方法。Executor主要是用于创建Statement对象,在创建过程中依靠 MappedStatement 对象将赋值内容给 sql 占位符进行绑定。

DefaultSqlSessionFactory:

在这里插入图片描述
Configuration:
在这里插入图片描述

InterceptorChain:
在这里插入图片描述
PageHelper:
在这里插入图片描述

Plugin:
在这里插入图片描述
在这里插入图片描述

PageHelper:
在这里插入图片描述

SqlUtil:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

MappedStatement:
在这里插入图片描述

观察控制台,可以看到mybatis框架执行的sql,已经进行了分页处理:

在这里插入图片描述

下面的时序图可以看到创建SqlSession对象的过程:
在这里插入图片描述

2. 自定义mybatis拦截器

2.1 自定义

MyBatis 自定义拦截器,可以拦截的接口有四种 Executor.class,StatementHandler.class,ParameterHandler.class 和 ResultSetHandler.class。在某种情景下,如果这四种接口自带的某个方法不能满足我们的要求时,就可以在不改动源码的情况下,建立一个自己的拦截器用于拦截接口的某个方法。

自定义mybatis的拦截器,需要实现Mybatis框架提供的Interceptor接口。具体实现过程如下:

第一步:自定义拦截器

package com.itheima.interceptor;

import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import java.util.Properties;

/**
 * 自定义mybatis拦截器
 * 
 */
@Intercepts(
        @Signature(method = "query",
                type = Executor.class,
                args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})
)
public class CustomInterceptor implements Interceptor {
    /**
     * 拦截时执行的逻辑
     * @param invocation
     * @return
     * @throws Throwable
     */
    public Object intercept(Invocation invocation) throws Throwable {
        System.out.println("被拦截方法执行前的操作。。。");
        Object proceed = invocation.proceed();
        System.out.println("被拦截方法执行后的操作。。。");
        return proceed;
    }

    /**
     * 拦截器用于封装目标对象
     
     * 通过该方法我们可以返回目标对象本身,也可以返回一个它的代理
     * @param o
     * @return
     */
    public Object plugin(Object o) {
        return Plugin.wrap(o, this);
    }

    /**
     * 用于在 Mybatis 配置文件中指定一些属性
     * @param properties
     */
    public void setProperties(Properties properties) {
    }
}

第二步:在mybatis配置文件中注册自定义的拦截器

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <plugins>
        <!-- com.github.pagehelper 为 PageHelper 类所在包名 -->
        <plugin interceptor="com.github.pagehelper.PageHelper">
            <!-- 设置数据库类型 Oracle,Mysql,MariaDB,SQLite,Hsqldb,PostgreSQL 六种数据库-->
            <property name="dialect" value="mysql"/>
        </plugin>
      	<!--注册自定义拦截器-->
        <plugin interceptor="com.itheima.interceptor.CustomInterceptor"></plugin>
    </plugins>
</configuration>

可以通过断点调试方式确定自定义拦截器是否生效

2.2 解析

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值