Spring/Gradle下servlet-api依赖冲突致容器崩溃问题求助
解决Gradle中Servlet API版本冲突导致容器崩溃的问题
遇到这种Servlet API版本冲突的问题太常见了,尤其是老依赖(比如hadoop-core 1.2.1)自带低版本类的时候,我帮你梳理下最有效的解决步骤:
1. 精准排除hadoop-core里的servlet-api传递依赖
你之前用全局排除没彻底解决,是因为没精准针对hadoop-core的传递依赖下手。hadoop-core 1.2.1依赖的低版本servlet-api是javax.servlet:servlet-api:2.5,直接在引入hadoop-core的时候排除它:
dependencies { implementation('org.apache.hadoop:hadoop-core:1.2.1') { // 精准排除该依赖下的servlet-api exclude group: 'javax.servlet', module: 'servlet-api' // 要是上面的group匹配不到(有些老jar的依赖group是空),就换成这个 // exclude group: '', module: 'servlet-api' } // 记得补上你项目实际需要的高版本Servlet API,比如适配Tomcat 9的4.0.1版本 implementation 'javax.servlet:javax.servlet-api:4.0.1' }
2. 验证依赖是否清理干净
执行下面的命令生成依赖树,确认低版本的servlet-api已经消失:
./gradlew dependencies --configuration runtimeClasspath
搜索servlet-api关键字,确保只有你指定的高版本出现在依赖树里。
3. 特殊情况:hadoop-core自身打包了servlet-api类
有些老jar包(比如hadoop-core 1.2.1)会把依赖的类直接打包到自己的jar里,这种时候排除传递依赖没用,因为低版本的Servlet类已经在hadoop-core.jar内部了。这时候有两个方案:
- 优先升级hadoop-core:如果业务允许,升级到2.x及以上版本,这些版本不再把servlet-api类打包进去,而是通过正常的传递依赖引入,从根源解决问题。
- 用Shadow插件剔除内置类:如果没法升级,就用Gradle的Shadow插件把hadoop-core里的低版本Servlet类删掉:
之后用Shadow生成的jar包启动容器,就能避免低版本类的干扰。plugins { id 'com.github.johnrengelman.shadow' version '7.1.2' } shadowJar { // 移除hadoop-core中的javax.servlet包下所有类 exclude 'javax/servlet/**' }
4. 调整容器类加载顺序(可选)
如果是Tomcat这类容器,还可以调整类加载顺序,确保项目依赖的高版本Servlet API优先被加载。比如在Tomcat的context.xml里添加:
<Context antiResourceLocking="true" antiJARLocking="true"> <!-- 让WEB-INF/lib里的jar优先于容器的类加载 --> <Loader delegate="false"/> </Context>
这样能进一步避免容器误加载低版本的Servlet类。
内容的提问来源于stack exchange,提问作者Ben Whitely
相关产品推荐
相关产品推荐

