JBOSS EAP 6.4升级7.4部署报NoClassDefFoundError求非移除解法
问题根因
报错核心是类加载版本冲突:
- JBoss EAP 7.4.3 自身模块体系内置了对应版本的Tomcat EL、WebSocket实现及工具类,其中就包含
org.apache.tomcat.util.res.StringManager,但内置版本和引入的9.0.58版本Tomcat embed包不兼容。 - 当前仅在应用中引入了
tomcat-embed-el-9.0.58、tomcat-embed-websocket-9.0.58两个依赖,未引入同版本的tomcat-embed-core(StringManager类实际存在于这个包中)。EAP默认类加载优先级是优先加载服务器全局模块的类,会出现“加载了应用自带的高版本Tomcat EL/WebSocket类,却去服务器模块路径下找低版本StringManager类”的错配,直接抛出类不存在的错误。
可行解决方案(无需移除pom中要求保留的Tomcat依赖)
- 方案1:通过JBoss专属部署配置做类加载隔离(优先推荐)
在项目src/main/webapp/WEB-INF/路径下新增jboss-deployment-structure.xml配置文件,排除服务器自带的Tomcat相关全局模块,强制类加载时优先读取应用自带的依赖包,从根源避免版本混装:
<?xml version="1.0" encoding="UTF-8"?> <jboss-deployment-structure> <deployment> <!-- 排除JBoss全局模块中内置的Tomcat相关组件,避免和应用内依赖冲突 --> <exclusions> <module name="org.apache.tomcat.embed.el"/> <module name="org.apache.tomcat.embed.websocket"/> <module name="org.apache.tomcat.util"/> </exclusions> <!-- 配置类加载优先读取应用WEB-INF/lib下的自有依赖 --> <local-last value="false"/> </deployment> </jboss-deployment-structure.xml>
配置完成后重新打包部署即可,不需要改动现有pom的依赖声明。
- 方案2:补齐同版本Tomcat embed核心依赖
现有依赖缺失同版本的tomcat-embed-core包才会找不到StringManager类,在pom中补充和现有两个Tomcat依赖完全同版本的core包,同时排除会和EAP冲突的servlet-api,不需要删除原有依赖:
<dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-core</artifactId> <version>9.0.58</version> <exclusions> <!-- 排除servlet-api,避免和EAP自带的servlet实现冲突 --> <exclusion> <groupId>jakarta.servlet</groupId> <artifactId>jakarta.servlet-api</artifactId> </exclusion> </exclusions> </dependency>
补齐后三个tomcat-embed包版本完全对齐,应用自带的依赖中已经包含完整的对应类,不管类加载优先级如何都不会出现类缺失。
- 方案3:调整Maven依赖作用域适配外部容器部署规则
按照Spring Boot外部容器部署的标准规则调整依赖作用域,不需要删除要求保留的两个Tomcat依赖,仅调整作用域即可避免冲突:
<!-- 内置Tomcat标记为provided,部署时由EAP容器提供对应能力 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> <!-- 保留要求必须引入的两个Tomcat依赖,调整作用域为runtime --> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-el</artifactId> <version>9.0.58</version> <scope>runtime</scope> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-websocket</artifactId> <version>9.0.58</version> <scope>runtime</scope> </dependency>
注意事项
优先选择方案1,该方案不需要调整上层要求固化的pom依赖配置,仅通过部署侧的类加载规则隔离就能解决冲突,适配成本最低,不会影响其他环境的依赖校验规则。配置完成后清理EAP的部署缓存、重启服务再发布应用即可。
内容的提问来源于stack exchange,提问作者Ritesh_RM
相关产品推荐
相关产品推荐

