欢迎关注方志朋的博客,回复”666“获面试宝典

来源:https://blog.csdn.net/qq_38245668/article/details/105984171/

前言

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

简单的 分页执行过程:

1.设置 page 参数

2.执行 query 方法

3.Interceptor 接口 中校验 ThreadLocal 中是否存在有设置的 page 参数

4.存在 page 参数,重新生成 count sql 和 page sql,并执行查询。不存在 page 参数,直接返回 查询结果

5.执行 LOCAL_PAGE.remove() 清除 page 参数

问题场景

观察上述的执行过程,可以发现,如果在第 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() 即可。

实现方式:

1.使用 aop,对所有 controller 进行处理

2.实现 HandlerInterceptor 或者 WebRequestInterceptor 对 request 请求的拦截器接口,通过 afterCompletion 方法执行 LOCAL_PAGE.remove() 。— 推荐,实现方式简单

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

public class PageLocalWebInterceptor implements HandlerInterceptor {@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// PageHelper.clearPage() 内部调用 LOCAL_PAGE.remove()PageHelper.clearPage();}
}

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

@Configuration
public class FrameworkAutoConfig implements WebMvcConfigurer {@Override
public void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new PageLocalWebInterceptor());
}

热门内容:
  • 干掉visio,这个画图神器真的绝了!!!

  • 面试官问:生成订单30分钟未支付,则自动取消,该怎么实现?

  • 不是我吹,这个idea插件你真没用过!

  • 比 Xshell 还好用的 SSH 客户端神器,MobaXterm 太爱了!

  • RedisJson 横空出世,性能碾压ES和Mongo!

最近面试BAT,整理一份面试资料《Java面试BAT通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。
获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。

明天见(。・ω・。)ノ♡

PageHelper 使用 ThreadLocal 的线程复用问题相关推荐

  1. ThreadLocal使用时因线程复用导致数据混乱分析

    ThreadLocal使用时因线程复用导致数据混乱分析 本文主要阐述使用ThreadLocal遇到数据混乱情况下的具体分析和解决过程 ThreadLocal原理 网上有很多介绍,不做详细介绍主要有四个 ...

  2. 当ThreadLocal碰上线程池

    ThreadLocal使用 ThreadLocal可以让线程拥有本地变量,在web环境中,为了方便代码解耦,我们通常用它来保存上下文信息,然后用一个util类提供访问入口,从controller层到s ...

  3. 线程池中阻塞队列的作用?为什么是先添加列队而不是先创建最大线程?线程池中线程复用原理

    1.一般的队列只能保证作为一个有限长度的缓冲区,如果超出了缓冲长度,就无法保留当前的任务了,阻塞队列通过阻塞可以保留住当前想要继续入队的任务.阻塞队列可以保证任务队列中没有任务时阻塞获取任务的线程,使 ...

  4. Java 线程池中的线程复用是如何实现的?

    前几天,技术群里有个群友问了一个关于线程池的问题,内容如图所示: 关于线程池相关知识可以先看下这篇:为什么阿里巴巴Java开发手册中强制要求线程池不允许使用Executors创建? 那么就来和大家探讨 ...

  5. ThreadLocal和线程同步机制的对比

    ThreadLocal和线程同步都是为了解决多线程中相同变量的访问冲突问题,那么,二者的区别在哪里?和线程同步机制对比,ThreadLocal有什么优势? 同步机制中通过对象的锁机制保证同一时间只有一 ...

  6. Java多线程学习十:线程池实现“线程复用”的原理

    线程复用原理 我们知道线程池会使用固定数量或可变数量的线程来执行任务,但无论是固定数量或可变数量的线程,其线程数量都远远小于任务数量,面对这种情况线程池可以通过线程复用让同一个线程去执行不同的任务,那 ...

  7. 为什么用线程池?解释下线程池参数?线程池处理流程?阻塞队列的作用?为什么是先添加列队而不是先创建最大线程?线程池中线程复用原理?

    为什么用线程池?解释下线程池参数? 1.降低资源消耗:提高线程利用率,降低创建和销毁线程的消耗. 2.提高响应速度:任务来了,直接有线程可用可执行,而不是先创建线程,再执行. 3.提高线程的可管理性: ...

  8. 文化袁探索专栏——线程池执行原理|线程复用|线程回收

    文化袁探索专栏--Activity.Window和View三者间关系 文化袁探索专栏--View三大流程#Measure 文化袁探索专栏--View三大流程#Layout 文化袁探索专栏--消息分发机 ...

  9. java线程池newfi_Java 线程池中的线程复用是如何实现的?

    前几天,技术群里有个群友问了一个关于线程池的问题,内容如图所示: 那么就来和大家探讨下这个问题,在线程池中,线程会从 workQueue 中读取任务来执行,最小的执行单位就是 Worker,Worke ...

最新文章

  1. 北京理工大学计算机学院张教授,北京理工大学嵩天教授做客信息学院
  2. TCP/IP 与OSI结构图
  3. codevs2693 上学路线(施工)
  4. “苹果光环”褪色后,瑞声靠什么坐稳头把交椅?
  5. 自定义浏览器协议,实现web程序调用本地程序
  6. 程序员面试金典 - 面试题 10.10. 数字流的秩(map/树状数组)
  7. php 5.2.6升级,Centos5.5 简单方法升级php到php5.2.6
  8. 数字逻辑要不要认真学_认真认真
  9. 小型局域网环境下搭建的文件中转系统
  10. 黑群晖vmm专业版_教你群晖用自带的VMM虚拟机安装精简版win10系统教程
  11. html文档怎么设置默认浏览器打开,win10系统如何设置HTML文件指定浏览器打开?...
  12. MySQL数据库(1):数据库 Database 基本概念
  13. uniapp使用百度地图
  14. 想用 Google 搜索引擎吗,看这篇文章吧!!!
  15. my firebox plugin list
  16. Codeforces 776B 776C 程序(夏洛克专场)
  17. 深入浅出HTML(针对后端攻城狮)
  18. 触发器相关概念与应用
  19. Mac视频播放器:zFuse Pro
  20. Marbles Gym - 101908B

热门文章

  1. linux c一站式编程 pdf,《Linux·C编程一站式学习》·(宋劲杉)·文字版.pdf
  2. centos ezhttp mysql_CentOS安装mysq
  3. SpringBoot 中 JPA 的使用
  4. 023 判断出栈顺序是否正确
  5. Entity Framework应用:根据实体的EntityState状态实现增删改查
  6. Hdu_2063 过山车 -最大匹配(邻接表版)
  7. IQKeyboardManager使用方法
  8. Android Layer List 使用实现实例
  9. socket通信——通过Udp传输方式,将一段文字数据发送出去
  10. 高手讲解PHP遍历数组的方法