


先上结论:tomcat7.0-106之后的版本(包括8.5xx之后的版本,只是下了个较新的测试)改了DefualtServerlet类checkIfNoneMatch方法中的比较逻辑,导致用java中引号"与页面传过来被转义了accssi码的引号"进行比较,使结果不成立,返回了400。处理方法:在DefualtServerlet类中将界面中的If-None-Match对应的字符串中的引号"使用repalceAll替换成"即可。(只是解决问题不用看下面的内容了,下面只是作为个人记录)
补充:
1、java文件路径:org.apache.catalina.servlets.DefaultServlet
2、class文件路径:apache-tomcat-7.0.109\lib\catalina.jar——>org.apache.catalina.servlets.DefaultServlet
3、增加的内容:
headerValue = headerValue.replaceAll(""","\"");
4、前后端引号的应该在其它类中有其它的统一处理方式,我为了方便没有接着找下去。
这次问题不难解决,对我而言,难的是处理此问题的思路和定位到此问题,由于之前没有处理过这样隐藏比较深的源码问题,没有经验,定位问题不得法,以前有问题都是找度娘给答案的,此次不知道是搜索关键字不对还是没人提到这个问题,没找到答案,问了几个群,可能大家都不用tomcat了吧,也没有大佬能给出答案,无奈一步步尝试。
背景和定位过程:安全扫描,说以前版本有安全漏洞(吐槽一下:今年升级了三次了),只能进行tomcat升级了,我直接从tomcat 7.0-100升级到了7.0-109,后发现静态资源加载有问题,每天第一次登录,背景图加载出问题,F12查看图片请求时不时报400,谷歌浏览器还不容易发现问题,火狐和ie浏览器比较容易观察。
当时同时改了页面业务代码发版,还以为是自己业务界面改出来的bug,由于此现象一天只会出现一次,非常难观察,当时还没将图片显示不出与报错联系起来,因为后面有报错但图片还是能显示,谷歌浏览器更是经常看不到此报错。
后面找度娘一顿操作,都不奏效(再次吐槽一下,现在的垃圾文章太多了,各种复制粘贴,转载,找的一堆文章都是相同的,麻烦你们那些人能网上搜到的,你们又没有新的问题点,也没有新的解决方案,不要再发文章出来了行不行,制造了大量的信息垃圾),此时业务同事已经开始说时间拖得太久了(每次改了后要第二天观察页面能不能刷新出来。。。),后来想到页面增加随机数能解决静态资源加载的问题,于是死马当活马医,先将F12看到400报错处理了,惊喜发现了,后面没有每天第一次出现登录不展示背景图的问题了,变成两三天或三四天了(整个人裂开了。。。),后面继续查找,发现页面有引用其它界面,其它界面中又有调用静态资源,无奈一个个调整,好在页面不是很多。处理后基本算是正常了,应付过了业务同事了。
但自己测试时发现还是有些插件有时加载不出来,比如说日期插件,虽然刷新一下能好,业务同事也没反映此情况,但还是默默记在心里了,还有一个就是css文件中也有图片链接,此位置的请求加不了随机数,我又不会,又是一顿度娘未果(再次吐槽:不要发重复的文章了,真的很浪费时间),老外有提到一个利用jQuery实现css随机时间的操作,我前端菜,又嫌麻烦,就没进行相关改造了,暂时将此事搁置了。
在此期间,有怀疑过新版本的tomcat有bug,但未进行测试,因为就算是新版本bug,也不可能将tomcat还原成原来版本,等tomcat开发人员进行更新了,毕竟安全扫描过不去,期间有去官网看最近tomcat各版本bug修复记录,但貌似都没有提到400的错误或更新导致此错误,包括网上查询都没人提到新版本的400问题,其它原因导致的400的文章倒是一大堆重复的文章,后面拖了一段时间后,发现不再支持tomcat 7版本的更新了。再后来工作闲暇之余,将7.0.100到7.0.109逐个测试了一下,确认此问题是tomcat 7.0.106带入的,至此,算是触到了此问题的门路了,但怎么定位是哪里导致的又是一个费事的地方,前面提到过,去官网bug修复记录里查看,未找到106版本关于此问题的描述。后面将105、106源码都导出来,未发现哪里变动导致的,在idea中查找400,一堆信息,用比较工具查看,106版本相对于105版本改变的文件也非常多,快速看了两遍也没发现问题,也没耐心看下去,其实再细心点也能发现问题,实在没办法,使用源码跑一下项目,期望通过打一些断点能够找到问题所在,最终只能是失望了,后面忙着业务开发就暂且未管了。
最近又有空余时间了,去看了些tomcat源码文章(大量重复文章,讲重点的内容时又一笔带过),还是没有思路,于是又用比较工具查看,这次时间较多,耐心的一个文件一个文件的查看变动的位置,终于在changelog文件里看到400字样,当时那个心情呀,一则因为终于找到问题所在了,一则因为自己不清楚源码中有changelog这个文件,还有对源码的不熟悉。后来为了查找这次修改改动了哪些文件,又去git上拉源码,查找变更日志,将此次变更的几个文件逐一查看,终于在DefaultServlet的变更中看到了HttpServletResponse.SC_BAD_REQUEST常量,点进去一看,果然对应的数值就是400了,其实前面使用对比工具比较差异时,也看到了这个类和这个常量,只是没有细心考虑。于是将断点都设置在这个方法中了,确认是进到此方法,在下图图中第④处返回了错误信息,当时也是不清楚为啥走到这里了,然后继续查找相关文章,使用DefaultServlet、checkIfNoneMatch、"If-None-Match"查到了些相关文章,但都是以前版本的tomcat,对此还是无解,后面又无意间找到文章提到了304,指出页面的静态资源再次请求时会将"If-None-Match"对应的值与此类中再次生成的值进行比较,相同则返回304,浏览器使用自身缓存的静态资源。再次debug并进比较方法中,发现浏览器界面传过来的的引号被转义成accssi码了,比较方法中未作任何转换直接进行比较,导致将引号"与&进行比较,导致第③处返回null,进入图中第④处后返回400给浏览器了,图片就加载失败了。

将此处界面传入的值中转义过的分号替换掉后,问题得到解决,将tomcat源码编译替换测试环境的文件后,测试环境也正常,于是将原来加过了的随机数还原,测试后也正常,至此,整个修改经历告一段落。
问题反思:
1、确认问题时,采用控制变量,先将自己业务代码还原,进行测试观察,再将tomcat等框架或插件还原,定位是什么插件或模块引起的问题,然后再使用不同版本确认哪一个版本带来的问题。
2、确认源码有问题后,先看官网问题修复记录,再看源码变更记录,将问题可能出现的范围尽量缩小,缩小后才去debug测试,不然直接debug极其费时间和精力。
3、还是需要经常想静静,每次处理问题没思绪后,继续处理都是越想越乱,一顿王八拳乱挥,这里试一下那里试一下,有新的思路都是停止一段时间再次处理的时候,可现在国内公司都是赶工形式吧,不会让你有那么多时间去处理一个问题,哪里会让你有时间想静静,只会说你工作不饱和,这也是和国外的创造力、创新能力有关吗,不得而知。。。
4、现在重复的文章太多,大量抄袭转载的,需要找到方法快速去掉重复的文章,提升获取信息的效率,排除垃圾信息的影响。
如有大佬看到了最后,帮忙提提意见,指导指导,如果有其他人已写此问题处理方法,麻烦告知链接,确认后隐藏此文章,降低大家搜到重复文章的概率。
在升级到Tomcat 7.0.106及更高版本后,遇到静态资源加载报错400的问题。原因是DefaultServlet类中If-None-Match比较逻辑改变,导致与页面传递的转义引号不匹配。解决方案是在DefaultServlet中替换If-None-Match字符串中的引号。此外,文章分享了问题定位和解决过程,强调了处理类似问题的方法和思考。
1万+





