JBoss/Wildfly部署war时多jar同名类冲突如何设置加载优先级
JBoss/Wildfly WAR包类加载优先级规则及feign依赖冲突解决方案
一、JBoss/Wildfly WEB-INF/lib目录jar包加载优先级规则
- 父类优先委托规则:默认情况下JBoss类加载器会优先加载服务器自带的公共类库,之后才会加载应用WEB-INF/lib目录下的jar包。如需改为优先加载应用自身类,可在WEB-INF目录下添加
jboss-deployment-structure.xml配置<local-last value="true" />开启应用类优先模式。 - 同目录内jar包加载规则:WildFly 10及之后版本,WEB-INF/lib下的jar包默认按文件名字典序加载,字典序越靠前的jar包越先被加载;JBoss 8及更早版本没有固定加载顺序,和操作系统文件遍历顺序、jar包写入目录的顺序相关,不可控。
你遇到的报错
java.lang.NoSuchMethodError: feign.Response.create(ILjava/lang/String;Ljava/util/Map;Lfeign/Response$Body;)Lfeign/Response;,就是8.18.0版本的feign-core先被加载,缺少高版本新增的create方法导致的。
二、冲突解决方案
方案1:Maven依赖调解(推荐,无需修改服务器配置)
利用Maven自带的依赖锁定和排除规则,统一feign-core版本为高版本,同时排除低版本依赖的传递引入:
<!-- 第一步:在dependencyManagement节点全局锁定feign-core版本为10.2.3 --> <dependencyManagement> <dependencies> <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-core</artifactId> <version>10.2.3</version> </dependency> </dependencies> </dependencyManagement> <!-- 第二步:给8.18.0版本的feign-httpclient排除传递引入的低版本feign-core --> <dependency> <!-- Required to use PATCH --> <groupId>com.netflix.feign</groupId> <artifactId>feign-httpclient</artifactId> <version>8.18.0</version> <exclusions> <exclusion> <groupId>com.netflix.feign</groupId> <artifactId>feign-core</artifactId> </exclusion> </exclusions> </dependency>
绝大多数场景下feign-httpclient 8.x可以兼容10.x版本的feign-core,只要业务代码没有用到8.x版本特有的已废弃API,该方案可直接生效。
方案2:调整JBoss加载顺序
如果方案1测试出现兼容性问题,必须保留两个版本的feign-core,可手动指定高版本优先加载:
- WildFly 10+版本:直接修改feign-core-10.2.3.jar的文件名,让它的字典序比feign-core-8.18.0.jar更靠前即可,比如重命名为
0-feign-core-10.2.3.jar。 - 旧版本JBoss:在WEB-INF下添加
jboss-deployment-structure.xml显式指定资源加载顺序:
<jboss-deployment-structure> <deployment> <resources> <!-- 把高版本feign-core放在最前面,优先加载 --> <resource-root path="WEB-INF/lib/feign-core-10.2.3.jar" /> <resource-root path="WEB-INF/lib/feign-okhttp-10.1.0.jar" /> <resource-root path="WEB-INF/lib/feign-httpclient-8.18.0.jar" /> <!-- 其余依赖按正常顺序补充即可 --> </resources> <local-last value="true" /> </deployment> </jboss-deployment-structure>
方案3:模块隔离(极端兼容场景用)
如果两个版本的feign-core完全无法兼容,都必须保留使用,可以使用JBoss的模块隔离机制,将两个版本的feign相关依赖分别封装为独立的JBoss模块,业务代码按需引用对应模块的类即可,该方案改造成本较高,仅在前两个方案不可行时使用。
内容的提问来源于stack exchange,提问作者RahulNans
相关产品推荐
相关产品推荐

