Tomcat
配置Tomcat9 /webapps/WEB-INF/lib/jar的加载顺序
前言
在开发环境的linux部署Tomcat不会有jar包冲突,换了linux机器报错NoClassDefFoundError
事故描述
冲突jar包 calcite 的 acatica-1.16.jar 和 actica-core-1.18.jar
ps:接手的项目,公司环境没有问题,客户现场部署出现NoClassDefFoundError,经查是因为Tomcat7以后lib包加载时是无序的,这点有兴趣的朋友可以研究下tomcat源码,临时解决方案是将客户现场的Tomcat降级为Tomcat7,Tomcat7及以下是按照jar包的字母顺序加载的
解决
在content.xml中添加下面的PreResources配置,可以指定优先加载的jar
<Resources>
<PreResources className="org.apache.catalina.webresources.FileResourceSet"
base="${catalina.base}/webapps/项目/WEB-INF/lib/架包.jar"
webAppMount="/WEB-INF/lib/架包.jar" />
</Resources>
配置中 className=“org.apache.catalina.webresources.FileResourceSet” 是固定的,开始以为是要指定冲突的class名,搞了半天是固定的
举例:
<Context>
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<WatchedResource>WEB-INF/tomcat-web.xml</WatchedResource>
<WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
<Resources>
<PreResources className="org.apache.catalina.webresources.FileResourceSet"
base="${catalina.base}/webapps/xxx/WEB-INF/lib/acatica-1.16.jar"
webAppMount="/WEB-INF/lib/acatica-1.16.jar" />
</Resources>
</Context>
PreResources
前提资源在主资源之前加载。它们将按照定义的顺序进行搜索。要配置PreResources,在元素中嵌套一个元素
PostResources
翻译
排序
除了上面描述的资源集之外,标准实现还维护ClassResources,它表示映射到/WEB-INF/classes的JAR文件中包含的类。这使得其他组件只需一个调用就可以搜索类,而不是先搜索/WEB-INF/classes,然后再搜索/WEB-INF/lib中的jar文件。当web应用程序启动时,ClassResources从映射到/WEB-INF/lib的jar文件中填充。
因此,完整的搜索顺序为:
PreResources
MainResources
ClassResources
JarResources
PostResources
在web应用程序启动时,ClassResources和JarResources的填充意味着需要谨慎地正确添加基于JAR的资源,以获得所需的行为。考虑下面的例子:
<Resources>
<PostResources base="D:\Projects\external\classes"
className="org.apache.catalina.webresources.DirResourceSet"
webAppMount="/WEB-INF/classes"/>
<PostResources base="D:\Projects\lib\library1.jar"
className="org.apache.catalina.webresources.FileResourceSet"
webAppMount="/WEB-INF/lib/library1.jar"/>
</Resources>
因为这两个资源都是PostResources,所以可以预期D:\Projects\external\classes将在D:\Projects\lib\library1.jar之前加载。然而,通过使用FileResourceSet添加JAR, JAR被映射到/WEB-INF/lib,并将在应用程序启动时与/WEB-INF/lib中的其他JAR一起处理。JAR文件中的类将被添加到ClassResources中,这意味着它们将在D:\Projects\external\classes之前被搜索。如果期望的行为是在D:\Projects\lib\library1.jar之前加载D:\Projects\external\classes,那么需要一个稍微不同的配置:
<Resources>
<PostResources base="D:\Projects\external\classes"
className="org.apache.catalina.webresources.DirResourceSet"
webAppMount="/WEB-INF/classes"/>
<PostResources base="D:\Projects\lib\library1.jar"
className="org.apache.catalina.webresources.JarResourceSet"
webAppMount="/WEB-INF/classes"/>
</Resources>
简而言之,JAR文件应该添加为映射到/WEB-INF/类的JarResourceSet,而不是使用映射到/WEB-INF/lib的FileResourceSet。