Spring Boot Jersey部署Tomcat8.5遇AbstractMethodError问题求助
Hey there, let's work through this frustrating deployment issue you're facing! When your Spring Boot Jersey app runs fine in STS but throws a javax.servlet.ServletException with WsFilter.doFilter in the stack trace on Tomcat 8.5, it's almost always tied to hidden dependency conflicts or Tomcat's WebSocket filter clashing with Jersey. Here's how to resolve it step by step:
1. Hunt Down and Eliminate All Jersey 1.x Dependencies
Sometimes excluding direct Jersey 1.x dependencies isn't enough—indirect dependencies from third-party libraries can sneak in. Let's get a full view of your dependency tree first:
mvn dependency:tree
Look for any dependencies starting with com.sun.jersey (that's Jersey 1.x territory). For every occurrence, add an exclusion in your pom.xml, even if it's coming from a Spring Boot starter:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jersey</artifactId> <exclusions> <exclusion> <groupId>com.sun.jersey</groupId> <artifactId>jersey-core</artifactId> </exclusion> <exclusion> <groupId>com.sun.jersey</groupId> <artifactId>jersey-server</artifactId> </exclusion> <!-- Add exclusions for ALL com.sun.jersey artifacts you find --> </exclusions> </dependency>
Double-check other dependencies (like client libraries or legacy integrations) that might be pulling in Jersey 1.x and exclude those too.
2. Adjust Tomcat's WebSocket Filter (or Disable It)
Tomcat's WsFilter is often the culprit here, especially if your app doesn't use WebSocket functionality. Here are two ways to handle it:
Option A: Disable WsFilter Completely (If You Don't Need WebSockets)
Add a Spring Boot configuration class to disable the filter:
import org.apache.tomcat.websocket.server.WsFilter; import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import javax.servlet.DispatcherType; import java.util.EnumSet; @Configuration @Order(Ordered.HIGHEST_PRECEDENCE) public class TomcatWsFilterConfig implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> { @Override public void customize(TomcatServletWebServerFactory factory) { factory.addContextCustomizers(context -> { // Override the default WsFilter mapping to disable it context.addFilterMap(context.findFilterMap("wsFilter")) .setDispatcherTypes(EnumSet.noneOf(DispatcherType.class)); }); } }
Option B: Modify Filter Mapping to Avoid Conflict
If you do need WebSockets, adjust the filter's dispatcher types to exclude async processing (which Jersey uses heavily):
Create a WEB-INF/web.xml in your WAR project with this config:
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <filter> <filter-name>wsFilter</filter-name> <filter-class>org.apache.tomcat.websocket.server.WsFilter</filter-class> </filter> <filter-mapping> <filter-name>wsFilter</filter-name> <url-pattern>/*</url-pattern> <!-- Remove ASYNC dispatcher to prevent clash with Jersey --> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> <dispatcher>INCLUDE</dispatcher> <dispatcher>ERROR</dispatcher> </filter-mapping> </web-app>
3. Verify Your Spring Boot Jersey Configuration
Make sure your Jersey setup is using pure Jersey 2.x APIs (no Jersey 1.x imports):
Example ResourceConfig Class (class1)
import org.glassfish.jersey.server.ResourceConfig; import org.springframework.stereotype.Component; @Component public class JerseyAppConfig extends ResourceConfig { public JerseyAppConfig() { // Register your resource classes (like class2) register(YourResourceClass.class); } }
WAR Deployment Bootstrapper
Ensure your main application class extends SpringBootServletInitializer for proper WAR deployment:
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; @SpringBootApplication public class YourApplication extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(YourApplication.class); } public static void main(String[] args) { SpringApplication.run(YourApplication.class, args); } }
4. Check Spring Boot-Tomcat Version Compatibility
Spring Boot 2.x is fully compatible with Tomcat 8.5, but if you're using Spring Boot 3.x, you'll need Tomcat 9+ (which would cause this kind of conflict). Double-check your spring-boot-starter-parent version in pom.xml to match Tomcat 8.5's support range.
After trying these steps, rebuild your WAR and redeploy to Tomcat 8.5—this should resolve the filter conflict and dependency issues.
内容的提问来源于stack exchange,提问作者Sanjay Shah

