配置Tomcat9 /webapps/WEB-INF/lib/jar的加载顺序

本文讲述了如何在Tomcat9的webapps/WEB-INF/lib目录下配置PreResources来确保特定jar包的优先加载,以解决NoClassDefFoundError问题,涉及了资源加载顺序和官方推荐的最佳实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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
前提资源在主资源之前加载。它们将按照定义的顺序进行搜索。要配置PreResources,在元素中嵌套一个元素

PostResources

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。

参考1
参考2
参考3

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值