如何让Tomcat优先加载Maven依赖Jar而非shared/lib下的Jar?
这个问题我碰到过好多次了,核心原因是Tomcat的类加载优先级规则在起作用:Tomcat的shared/lib目录属于Common类加载器的加载范围,而Web应用自己的WEB-INF/lib(Maven依赖默认打包到这里)属于Webapp类加载器。默认情况下,Webapp类加载器会先委托父类加载器(Common)加载类,所以如果shared/lib里有旧版本的Jar,Webapp就会直接用这个旧Jar的类,而不会去加载自己WEB-INF/lib里的新Jar。
下面是几个靠谱的解决办法,按优先级推荐:
1. 直接移除shared/lib里的旧Jar包(最推荐)
如果这个Jar不是Tomcat下多个Web应用共享依赖的,直接删掉tomcat/shared/lib里的旧版本Jar。这样Webapp类加载器就会自动加载自己WEB-INF/lib里由Maven引入的新Jar包,从根源上避免冲突。
2. 修改Web应用的类加载委托规则
如果必须保留shared/lib里的旧Jar(比如其他应用需要用),可以修改当前Web应用的类加载行为,让它优先加载自己的Jar:
- 在你的项目中创建
META-INF/context.xml文件(如果已经存在就直接修改),添加以下配置:
这个配置把<Context> <Loader delegate="false"/> </Context>delegate设为false后,Webapp类加载器会先尝试自己加载WEB-INF/lib里的类,只有找不到的时候才会委托父类加载器(Common)去加载,这样新Jar的类就会被优先加载。
3. 检查Maven依赖的Scope配置
确保你的Jar依赖在pom.xml里的scope是compile(默认值,不用特意写),而不是provided:
<!-- 正确的配置,Maven会把这个Jar打包到WEB-INF/lib --> <dependency> <groupId>xxx</groupId> <artifactId>xxx</artifactId> <version>新版本号</version> </dependency> <!-- 错误的配置,Maven不会打包这个Jar,会依赖容器提供,导致Tomcat用shared/lib的旧Jar --> <dependency> <groupId>xxx</groupId> <artifactId>xxx</artifactId> <version>新版本号</version> <scope>provided</scope> </dependency>
如果之前不小心设了provided,改成compile后重新打包部署即可。
4. 清理Tomcat缓存并重启
有时候Tomcat会缓存已加载的类,即使你修改了配置或Jar包,缓存的旧类依然会被使用:
- 停止Tomcat服务
- 删除
tomcat/work/Catalina/localhost/你的应用名目录下的所有内容 - 重新启动Tomcat,让它重新加载新的类文件
内容的提问来源于stack exchange,提问作者Tonyukuk
相关产品推荐
相关产品推荐

