前言
最近着手学习springboot,但想先自主学习SSM纯注解开发,理解其原理后学习springboot将会更加得心应手,容易理解。在此期间,遇见一个困扰我一星期的bug,在此期间我也各种调试,甚至深入到了Tomcat源码,也借机理解了ServletContainerInitializer的加载机制。
一、ServletContainerInitializer是什么?
Servlet3.0官方支持第三方插件植入,也就是可以抛弃web.xml再结合spring的注解,而要做的就是就是实现这个接口即可,spring-web也给我们做了实现,因此我们直接使用即可。完全可以做到纯注解开发,但由于Tomcat是外置而不像springboot内嵌Tomcat,因此也会有许多问题
二、同时有多个ServletContainerInitializer实现类的问题
比如:spring-web的SpringServletContainerInitializer和log4j-web的Log4jServletContainerInitializer。上述二者再SSM+日志开发中一定会遇到。但当同时使用时就会发生一些匪夷所思的bug。
当我同时使用时,发现只有Log4jServletContainerInitializer被Tomcat加载了,而SpringServletContainerInitializer根本没有被加载。在我寻找根源的过程就不一一列举。
三、原因及解决办法
在深入到tomcat的源码后,再通过一系列的调试,我发现不管如何,只能加载第一个,那我断定这个类根本就没有被tomcat扫描到,而我的控制台平时都会打印这么一句话
29-May-2021 17:23:51.583 信息 [RMI TCP Connection(3)-127.0.0.1] org.apache.jasper.servlet.TldScanner.scanJars 至少有一个JAR被扫描用于TLD但尚未包含TLD。 为此记录器启用调试日志记录,以获取已扫描但未在其中找到TLD的完整JAR列表。 在扫描期间跳过不需要的JAR可以缩短启动时间和JSP编译时间。
截个图吧
后来上网查找此句话的解决办法,也就是将其Tomcat根目录下的conf文件夹下的catalina.properties文件里的属性修改
将上述两处地方等号后面改为我这样的也就是*.jar之后解决