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
会把分页信息存入一个ThreadLoca
l变量中,在拦截到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