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_PAGEremove() 即可。实现方式:
这里使用第二种方式,实现 HandlerInterceptor 接口:
定义配置类,配置类需实现 WebMvcConfigurer 接口完成对于WebMvc的相关配置 ,注册 PageLocalWebInterceptor :
如果vo里有pageNum和pageSize 再加上配置文件里supportMethodsArguments= true,那么即使不使用PageHelperstartPage(pageNum,PageSize) 也会自动分页。
问题就在supportMethodsArguments这个参数,默认是false,因为我们也不太清楚该参数的含义,就给设置为了true。这里可通过两种方式解决这个问题,第一种删除supportMethodsArguments配置(不启用),这样分页的方法中必须调用PageHelperstartPage方法,第二种不要给pageNum和pageSize设置默认值或者变量名不要为这两个,这样PageHelper解析出来的值为空就不会进行分页。推荐第一种,因为第二种分页隐藏的比较深,不熟悉的人就很难找出问题点。
以上就是关于PageHelper 使用 ThreadLocal 的线程复用问题,你用对了吗全部的内容,包括:PageHelper 使用 ThreadLocal 的线程复用问题,你用对了吗、pagehelper分页自己调自己怎么回事、等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)