最近测试反馈一个问题,某个查询全量信息的接口,有时候返回全量数据,符合预期,但是偶尔又只返回1条数据,简直就是见鬼了,究竟是为什么出现这样的幽灵数据呢? 大胆猜测 首先我们
最近测试反馈一个问题,某个查询全量信息的接口,有时候返回全量数据,符合预期,但是偶尔又只返回1条数据,简直就是“见鬼”了,究竟是为什么出现这样的“幽灵数据”呢? 大胆猜测首先我们看了下这对代码的业务逻辑,非常的简单,总共没有几行代码,也没有分页逻辑,代码如下:
那么究竟是咋回事呢?讲道理不可能出现这种情况的啊,不要慌,我们加点日志,将日志级别调整为DEBUG,让日志飞一段时间。
果不其然,日志中出现了奇奇怪怪的分页参数,如下图所示: 果然是PageHelper这个开源框架搞的鬼,我想大家都用过吧,分页非常方便,那么究竟为什么别人都没问题,单单就我会出现问题呢? PageHelper工作原理为了回答上面的疑问,我们先看看PageHelper框架的工作原理吧。 PageHelper 是一个开源的 MyBatis 分页插件,它可以帮助开发者在查询数据时,快速的实现分页功能。 PageHelper 的工作原理可以简单概括为以下几个步骤:
PageHelper 的实现原理主要依赖于拦截器技术和反射机制,通过拦截查询语句并动态生成分页语句,实现了简单、高效、通用的分页功能。具体源码在下图的类中,非常容易看懂。 明白了PageHelper的工作原理后,反复检查代码,都没有调用过startPage,debug查看ThreadLocal中也没有分页信息啊,懵逼中。那我看看别人写的添加分页参数的代码吧,不看不知道,一看吓一跳。 原来有位“可爱”的同事竟然在查询后,加了一个分页,就是把分页信息放到线程的ThreadLocal中。 那大家是不是有疑问,丁是丁,矛是矛,你的线程关我何事?这就要说到我们的tomcat了。 Tomcat请求流程其实这就涉及到我们的tomcat相关知识了,我们一个浏览器发一个接口请求,经过我们的tomcat的,究竟是一个什么样的流程呢?
关于tomcat中使用线程池提交浏览器的连接请求的源码如下: 从而得知,你的连接请求是从线程池从拿的,而拿到的这个线程恰好是一个“脏线程”,在ThreadLocal中放了分页信息,导致你这边出现问题。 总结后来追问了同事具体原因,才发现是粗心导致的。有些bug总是出现的莫名其妙,就像生活一样。所以关键的是我们在使用一些开源框架的时候一定要掌握底层实现的原理、核心的机制,这样才能够在解决一些问题的时候有据可循。 |
2021-06-05
2021-05-27
2021-05-26
2021-06-05
2021-05-16