关于ThreadLocal(分页插件再分析)

1.应用场景

1.PageHelper的底层实现

2. @Autowired private HttpServletRequest request 或者 @Autowired private HttpSession session**

其底层实现为Spring对单例对象注入非单例实例的一个解决方案:Scoped Proxy, Spring巧妙地注入了一个装饰器代理了真实对象的操作。再继续往底层挖,实则是最终在代理逻辑中最后调用的是RequestContextHolder.currentRequestAttributes()

1.1分析ThreadLocal实现存取数据的方式

在这里插入图片描述

2.Mybatis分页插件的再分析

1.mybatis的分页插件就是使用了ThreadLocal来存放分页的数据,从而对Service层实现无侵入的分页实现

2.1关于注册mybatis Plugin

Mybatis的Plugin,实际上对应的是org.apache.ibatis.plugin.Interceptor接口,因为Intercepter的核心方法是plugin(Object target)方法,而对于该方法的实现,需要通过org.apache.ibatis.plugin.Plugin的静态方法wrap(Object target, Interceptor interceptor)对对应对象进行拦截再产生一个代理对象,说白了就是封装为Page对象时,会实现一个拦截器,拦截器基于Plugin中的一个wrap()方法对对象进行拦截,最后进行目标增强产生一个代理对象

在mybatis核心配置文件SqlMapConfig中注册分页插件

<plugins>

     <!-- com.github.pagehelper 为 PageHelper 类所在包名 -->

     <plugin interceptor="com.github.pagehelper.PageHelper">

            <!-- 设置数据库类型 Oracle,Mysql,MariaDB,SQLite,Hsqldb,PostgreSQL 六种数据库-->               <property name="dialect" value="mysql"/>

      </plugin>

</plugins>

2.2PageHelper

PageHelper拦截的是org.apache.ibatis.executor.Executor的query方法,传参的核心原理就是通过ThreadLocal进行的,当我们需要对某个查询进行分页查询时,我们可以调用Mapper进行查询前调用一次PageHelper.startPage(..),这样PageHelper会把分页信息存入一个ThreadLocal变量中,在拦截到query方法执行时会从对应的ThreadLocal中获得分页信息,进行分页处理完之后,清理ThreadLocal中的分页信息,使得每次的使用互不影响,同时对原来的查询代码没有任何的侵入性。

一般返回结果是一个java.util.List, Pagehelper分页查询后的结果会变成一个PageHelper分页查询后的结果会变成com.github.pagehelper.Page类型,其继承了java.util.ArrayList,所以不会对我们的方法声明造成影响。

简单使用:

public void test() {

    int pageNum = 2;//页码,从1开始

    int pageSize = 10;

    //每页记录数

     PageHelper.startPage(pageNum, pageSize);

    //指定开始分页

    UserMapper userMapper = this.session.getMapper(UserMapper.class);

    List<User> all = userMapper.findAll(); Page<User> page = (Page<User>) all;

    System.out.println(page.getPages()); System.out.println(page);

}

参考原文地址:https://blog.csdn.net/elim168/article/details/72820509 作者:elim168

猜你喜欢

转载自blog.csdn.net/qq_18361601/article/details/106755826