在Wildfly中部署含Jersey的Spring Boot WAR包
Hey Brian, let's troubleshoot that Wildfly WAR deployment issue you're facing—since you've already got the WAR compiled, the problem almost always ties to Spring Boot, Jersey, and Wildfly's built-in components clashing. Here are the most common fixes to work through step by step:
Spring Boot's default web starter includes an embedded Tomcat server, but Wildfly uses its own Undertow/JBoss Web container. Bundling Tomcat with your WAR will cause classpath conflicts that break startup.
Fix for Maven:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <!-- Wildfly provides this API, so mark it as provided --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency>
Fix for Gradle:
configurations { providedRuntime } dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-jersey' exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat' providedRuntime 'javax.servlet:javax.servlet-api:4.0.1' }
This tells Wildfly to use its own container instead of trying to run Tomcat, eliminating the most frequent conflict source.
Spring Boot needs to know how to bootstrap itself as a traditional WAR (not a standalone JAR with an embedded server). Modify your main application class to extend SpringBootServletInitializer:
@SpringBootApplication public class YourApplication extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { // Point to your application's main class return application.sources(YourApplication.class); } // Keep the main method for JAR mode public static void main(String[] args) { SpringApplication.run(YourApplication.class, args); } }
This overrides the default bootstrapping logic to play nice with Wildfly's servlet container lifecycle.
Wildfly ships with its own JAX-RS implementation (RESTEasy), which will clash with your Jersey setup. You have two solid options here:
Option A: Force Wildfly to Use Your Bundled Jersey
Create a jboss-deployment-structure.xml file in src/main/webapp/WEB-INF/ to exclude Wildfly's RESTEasy modules:
<jboss-deployment-structure> <deployment> <exclude-subsystems> <subsystem name="jaxrs" /> </exclude-subsystems> <exclusions> <module name="javax.ws.rs.api"/> <module name="org.jboss.resteasy.resteasy-jaxrs"/> <module name="org.jboss.resteasy.resteasy-jackson2-provider"/> </exclusions> </deployment> </jboss-deployment-structure>
This makes Wildfly ignore its own JAX-RS tools and use your project's Jersey dependencies instead.
Option B: Switch to RESTEasy (Wildfly's Native JAX-RS)
If you don't need to stick with Jersey, replace it with Spring Boot's RESTEasy starter to align with Wildfly:
<!-- Remove the Jersey starter --> <!-- <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jersey</artifactId> </dependency> --> <!-- Add RESTEasy starter --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-resteasy</artifactId> </dependency>
This is often the simpler long-term solution since it uses Wildfly's native tools, reducing deployment friction.
Since you're hosting Angular/JS files in src/main/resources, make sure Spring Boot serves them correctly in WAR mode. Double-check your application.properties:
# Map static resource locations to your frontend files spring.web.resources.static-locations=classpath:/static/,classpath:/public/ # Enable SPA fallback for Angular's routing spring.mvc.throw-exception-if-no-handler-found=true spring.web.resources.add-mappings=true
Also, configure Jersey to ignore static paths so it doesn't try to handle frontend requests:
@Component public class JerseyConfig extends ResourceConfig { public JerseyConfig() { // Register your Jersey API resources register(YourApiResource.class); // Tell Jersey to leave static files to Spring Boot property("jersey.config.server.servlet.filter.staticContentRegex", "/(css|js|images|html)/.*"); } }
If the above fixes don't resolve the issue, check Wildfly's server logs (usually at wildfly-xx.x.x/standalone/log/server.log). Look for:
ClassNotFoundExceptionorNoClassDefFoundError(signals missing/conflicting dependencies)DeploymentExceptionrelated to JAX-RS or servlet initialization- Errors about duplicate beans or context loading failures
Specific error messages will help you narrow down the exact conflict—for example, a javax.ws.rs.core.Application error is a clear sign of Jersey/RESTEasy clashing.
内容的提问来源于stack exchange,提问作者Brian S

