如何解决Spring Boot应用部署至WildFly27的NoClassDefFoundError问题
问题:Spring Boot WAR包部署到WildFly 27出现NoClassDefFoundError
环境信息
- Windows系统,全新安装WildFly 27
- 已通过
add-user.bat创建管理用户 - WildFly启动后,9990端口管理控制台、8080端口默认页面均可正常访问
项目配置与代码
pom.xml内容
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.5</version> <relativePath/> </parent> <groupId>com.example</groupId> <artifactId>wildfly-hello-world</artifactId> <version>1</version> <packaging>war</packaging> <name>wildfly-hello-world</name> <description>wildfly-hello-world</description> <properties> <java.version>17</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>${project.parent.version}</version> </plugin> </plugins> </build> </project>
主应用类代码
package com.example.wildflyhelloworld; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.web.bind.annotation.*; @SpringBootApplication public class WildflyHelloWorldApplication extends SpringBootServletInitializer { public static void main(String[] args) { SpringApplication.run(WildflyHelloWorldApplication.class, args); } @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(WildflyHelloWorldApplication.class); } } @RestController @RequestMapping class HelloWorldController { @GetMapping public String index() { return "Hello World"; } }
部署问题
将编译后的WAR包复制到WildFly的deployments文件夹后,部署时出现一系列NoClassDefFoundError错误,报错类明明存在于WEB-INF\lib下的spring-webmvc-5.3.23.jar中。
关键日志片段
org.jboss.modules.define] (MSC service thread 1-5) Failed to define class org.springframework.web.servlet.tags.form.AbstractHtmlElementTag in Module "deployment.wildfly-hello-world-1.war" from Service Module Loader: java.lang.NoClassDefFoundError: Failed to link org/springframework/web/servlet/tags/form/AbstractHtmlElementTag (Module "deployment.wildfly-hello-world-1.war" from Service Module Loader): javax/servlet/jsp/tagext/DynamicAttributes
求助
请问如何修复这些错误?或者提供一个能在WildFly 27上正常运行的Spring Boot示例?
解决方案
问题根源
WildFly 27基于Jakarta EE 10,使用的是jakarta.servlet命名空间的API;而你使用的Spring Boot 2.7.x依赖的是传统javax.servlet命名空间的API,两者不兼容,导致类加载时找不到javax.servlet.jsp.tagext.DynamicAttributes(WildFly提供的是jakarta.servlet.jsp.tagext.DynamicAttributes)。
修复方案(两种可选)
方案1:升级Spring Boot到3.x(推荐)
Spring Boot 3.x原生支持Jakarta EE 9+,与WildFly 27完全兼容。
- 修改pom.xml中的Spring Boot父版本为3.2.x或最新稳定版:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.2.0</version> <relativePath/> </parent>
- 移除手动添加的
javax.servlet-api依赖,Spring Boot 3.x会自动引入jakarta.servlet-api - 确保Java版本使用17+(Spring Boot 3.x要求)
- 主应用类无需修改,保持继承
SpringBootServletInitializer即可
方案2:在Spring Boot 2.7.x中适配WildFly 27
如果不想升级Spring Boot,需要通过依赖调整和WildFly配置来兼容:
- 调整pom.xml依赖:
- 移除
javax.servlet-api依赖,改为引入WildFly兼容的Jakarta API:
<!-- 移除原有javax.servlet-api依赖,添加以下内容 --> <dependency> <groupId>jakarta.servlet</groupId> <artifactId>jakarta.servlet-api</artifactId> <version>6.0.0</version> <scope>provided</scope> </dependency>- 排除spring-boot-starter-web中的JSP相关组件(你的项目是REST服务,无需JSP标签库):
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> </exclusion> <exclusion> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> </exclusion> </exclusions> </dependency> - 移除
- 添加WildFly部署描述符:
在src/main/webapp/WEB-INF下创建jboss-deployment-structure.xml,配置WildFly提供Jakarta API:<?xml version="1.0" encoding="UTF-8"?> <jboss-deployment-structure> <deployment> <dependencies> <module name="jakarta.servlet.api" export="true"/> <module name="jakarta.servlet.jsp.api" export="true"/> </dependencies> </deployment> </jboss-deployment-structure>
验证部署
修改后重新编译打包WAR包,复制到WildFly的deployments文件夹,等待部署完成后,访问http://localhost:8080/wildfly-hello-world-1(根据你的WAR包名称调整路径),即可看到"Hello World"输出。
内容的提问来源于stack exchange,提问作者Slevin
相关产品推荐
相关产品推荐

