vii. Conclusion整体看下来,似乎不会存在什么问题,但是我们可以考虑集中极端情况:如果使用了startPage(),但是没有执行对应的sql,那么就表明,当前线程ThreadLocal被设置了分页参数,可是没有被使用,当下一个使用此线程的请求来时,就会出现问题。如果程序在执行sql前,发生异常了,就没办法执行finally当中的clearPage()方法,也会造成线程的ThreadLocal被污染。所以,官方给我们的建议,在使用PageHelper进行分页时,执行sql的代码要紧跟startPage()方法。除此之外,我们可以手动调用clearPage()方法 ,在存在问题的方法之前。
2. How to solve the problem
1. 确保PageHelper 方法调用后紧跟 MyBatis 查询方法,在查询前不要写任何逻辑处理,因为任何代码都可能产生Exception并发生线程复用的问题。2. 如果原有不合理的代码太多,没办法一一修改,可以考虑Controller层增加切面,JSF接口增加Filter,手动调用clearPage()方法。代码示例如下:// 针对JSF接口的Filter@Slf4jpublic class BscJsfAspectForPageHelper extends AbstractFilter { public BscJsfAspectForPageHelper(){ } @Override public ResponseMessage invoke(RequestMessage requestMessage) { try { log.info("BscJsfAspectForPageHelper.invoke For JSF PageHelper.clearPage()"); PageHelper.clearPage(); }catch (Exception e){ log.error("BscJsfAspectForPageHelper.invoke发生异常,error msg:", e); } return getNext().invoke(requestMessage); }}// XML配置 <bean id="bscJsfAspectForPageHelper" class="com.jdl.bsc.aspect.BscJsfAspectForPageHelper" scope="prototype"> </bean>// 针对Controller的切面@Aspect@Component@Slf4jpublic class BscAspectForPageHelper{ @Pointcut("execution(public * com.jdl.bsc.controller.*.*(..)) ") public void bscAspectForPageHelper(){ } @Before("bscAspectForPageHelper()") public void doBefore(JoinPoint joinPoint) { try { log.info("BscAspectForPageHelper.doBefore For PageHelper.clearPage()"); PageHelper.clearPage(); }catch (Exception e){ log.error("BscAspectForPageHelper.doBefore发生异常,error msg:", e); } }}