PageHelper 使用 ThreadLocal 的线程复用问题,你用对了吗?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PageHelper 使用 ThreadLocal 的线程复用问题,你用对了吗?相关的知识,希望对你有一定的参考价值。

参考技术A

PageHelper 是较为常用的分页插件,通过实现 Mybatis 的 Interceptor 接口完成对 query sql 的动态分页,其中分页参数由 ThreadLocal 进行保存。

简单的 分页执行过程:

观察上述的执行过程,可以发现,如果在第 1 步和第 2 步 之间发生异常,那么 LOCAL_PAGE 中当前线程对应的 page 参数并不会 remove。

在不使用线程池的情况下,当前线程在执行完毕后会被销毁,这时 当前线程 中的 threadLocals 参数 将会被情况,也就清空 了 LOCAL_PAGE 中 当前线程的 page 参数。

但是如果使用了线程池,当前线程执行完毕,并不会被销毁,而是会将当前线程再次存放到池中,标记为空闲状态,以便后续使用。在后续使用这个线程的时候,由于 线程 的 threadLocals 依旧存在有值,尽管我们在第 1 步时未设置 page 参数,第 3 步 的也能获取到page参数,从而生成 count sql 和 page sql ,从而影响我们的正常查询。

SpringBoot 项目中会使用内置的 Tomcat 作为服务器,而Tomcat会默认使用线程来处理请求,从而便引发了上述问题。

因为Tomcat的线程是用来处理request请求,那么在请求完成时,清空当前线程的threadLocals 属性值,也就是执行 LOCAL_PAGE.remove() 即可。实现方式:

这里使用第二种方式,实现 HandlerInterceptor 接口:

定义配置类,配置类需实现 WebMvcConfigurer 接口完成对于WebMvc的相关配置 ,注册 PageLocalWebInterceptor :

pagehelper的使用

知识点:使用pagehelper实现分页功能

参考资料github上:https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/zh/HowToUse.md

(1)不是maven项目,则需要下载引用pagehelper和jsqlparser两个jar包

http://repo1.maven.org/maven2/com/github/pagehelper/pagehelper/

http://repo1.maven.org/maven2/com/github/jsqlparser/jsqlparser/0.9.5/

 

 

maven项目只需,直接在pom.xml中引入依赖

<dependency>

    <groupId>com.github.pagehelper</groupId>

   <artifactId>pagehelper</artifactId>

    <version>最新版本</version>

</dependency>

(2)在mybatis配置文件mybatis-config.xml中配置拦截器插件

 

 <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
    </plugins>

 

 

(3)在代码中使用分页功能

  例如:1.查询所有数据,然后分页

           Page<Object> page=PageHelper.startPage(4, 1);//4为第4页,1为每页的页数

           注意:紧跟着的第一个select方法会被分页
            EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);//查询所有数据

 

            2.需要连续显示多少页

           //navigatePages=5   传入要连续显示多少页
            PageInfo<Employee> info=new PageInfo<>(emps,5);
            System.out.println("当前页码"+info.getPageNum());
            System.out.println("总记录数"+info.getTotal());
            System.out.println("每页记录数"+info.getPageSize());
            System.out.println("总页码"+page.getPages());
            
            System.out.println("连续显示的页码");
            int[] nums=info.getNavigatepageNums();
            for (int i : nums) {
                System.out.println(i);
            }

效果:

   技术分享图片

   源码:https://github.com/shuaishuaihand/pagehelper.git

 

 

       

 















以上是关于PageHelper 使用 ThreadLocal 的线程复用问题,你用对了吗?的主要内容,如果未能解决你的问题,请参考以下文章

Mybatis PageHelper 使用的注意事项

面试问题

分页助手PageHelper学习

MyBatis分页插件:比PageHelper都要简单,使用很灵活,目前支持Oracle和MySQL

PageHelper 使用

pagehelper怎么计算总数的