Spring 6迁移集成Jersey 3后REST接口返回404 Not Found问题求助
问题:Spring 6.0.13集成Jersey 3.1.1时出现404错误
从Spring 5迁移到Spring 6.0.13,集成Jersey 3.1.1后访问REST接口返回404,且RestApplication构造函数中的日志未打印,说明Jersey应用未正确初始化。
WebInitializer代码
public class WebInitializer implements WebApplicationInitializer { @Override public void onStartup(ServletContext servletContext) throws ServletException { var webApplicationContext = new AnnotationConfigWebApplicationContext(); webApplicationContext.register(this.createContextConfig()); webApplicationContext.setServletContext(servletContext); servletContext.addListener(new ContextLoaderListener(webApplicationContext)); var dispatcherServlet = new DispatcherServlet(webApplicationContext); ServletRegistration.Dynamic theDispatcherServlet = servletContext.addServlet("dispatcherServlet", dispatcherServlet); theDispatcherServlet.setLoadOnStartup(1); theDispatcherServlet.addMapping("/*"); ServletRegistration.Dynamic jerseyRegistration = servletContext.addServlet("jerseyServlet", "org.glassfish.jersey.servlet.ServletContainer"); jerseyRegistration.setInitParameter("javax.ws.rs.Application", RestApplication.class.getName()); jerseyRegistration.setInitParameter("jersey.config.server.provider.packages", JerseyGsonProvider.class.getPackageName()); jerseyRegistration.setInitParameter("jersey.config.server.wadl.disableWadl", "true"); jerseyRegistration.addMapping("/rest/*"); jerseyRegistration.setLoadOnStartup(1); } .... }
RestApplication代码
@ApplicationPath("rest") public class RestApplication extends ResourceConfig { public RestApplication() { registerClasses(FooResource.class); register(new LoggingFeature(Logger.global.getLogger("JerseyLogger"), Level.FINE, LoggingFeature.Verbosity.PAYLOAD_ANY, 8192)); System.out.println("CLASSES REGISTERED IN JERSEY");//THIS MESSAGE IS NEVER PRINTED } }
FooResource代码
@Path("/foo") public class FooResource { @GET @Produces(MediaType.TEXT_HTML) @Path("/temp") public String temp() { return "<body>Hello! This is temp rest</body>"; } }
访问错误信息
HTTP ERROR 404 Not Found
URI: /rest/foo/temp
STATUS: 404
MESSAGE: Not Found
SERVLET: jerseyServlet
Powered by Jetty:// 12.0.3
日志信息
jakarta.ws.rs.NotFoundException: HTTP 404 Not Found at jersey.server@3.1.1/org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:258) [jersey-server-3.1.1.jar:?] at jersey.common@3.1.1/org.glassfish.jersey.internal.Errors$1.call(Errors.java:248) [jersey-common-3.1.1.jar:?] at jersey.common@3.1.1/org.glassfish.jersey.internal.Errors$1.call(Errors.java:244) [jersey-common-3.1.1.jar:?] at jersey.common@3.1.1/org.glassfish.jersey.internal.Errors.process(Errors.java:292) [jersey-common-3.1.1.jar:?] at jersey.common@3.1.1/org.glassfish.jersey.internal.Errors.process(Errors.java:274) [jersey-common-3.1.1.jar:?] at jersey.common@3.1.1/org.glassfish.jersey.internal.Errors.process(Errors.java:244) [jersey-common-3.1.1.jar:?] at jersey.common@3.1.1/org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:265) [jersey-common-3.1.1.jar:?] at jersey.server@3.1.1/org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:240) [jersey-server-3.1.1.jar:?] at jersey.server@3.1.1/org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:697) [jersey-server-3.1.1.jar:?] at jersey.container.servlet.core@3.1.1/org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:394) [jersey-container-servlet-core-3.1.1.jar:?] at jersey.container.servlet.core@3.1.1/org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:346) [jersey-container-servlet-core-3.1.1.jar:?] at jersey.container.servlet.core@3.1.1/org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:357) [jersey-container-servlet-core-3.1.1.jar:?] at jersey.container.servlet.core@3.1.1/org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:311) [jersey-container-servlet-core-3.1.1.jar:?] at jersey.container.servlet.core@3.1.1/org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:205) [jersey-container-servlet-core-3.1.1.jar:?] at org.eclipse.jetty.ee10.servlet@12.0.3/org.eclipse.jetty.ee10.servlet.ServletHolder$NotAsync.service(ServletHolder.java:1370) [jetty-ee10-servlet-12.0.3.jar:?] at org.eclipse.jetty.ee10.servlet@12.0.3/org.eclipse.jetty.ee10.servlet.ServletHolder.handle(ServletHolder.java:736) [jetty-ee10-servlet-12.0.3.jar:?] at org.eclipse.jetty.ee10.servlet@12.0.3/org.eclipse.jetty.ee10.servlet.ServletHandler$ChainEnd.doFilter(ServletHandler.java:1609) [jetty-ee10-servlet-12.0.3.jar:?] at org.eclipse.jetty.ee10.websocket.servlet@12.0.3/org.eclipse.jetty.ee10.websocket.servlet.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:195) [jetty-ee10-websocket-servlet-12.0.3.jar:?] at org.eclipse.jetty.ee10.servlet@12.0.3/org.eclipse.jetty.ee10.servlet.FilterHolder.doFilter(FilterHolder.java:205) [jetty-ee10-servlet-12.0.3.jar:?] at org.eclipse.jetty.ee10.servlet@12.0.3/org.eclipse.jetty.ee10.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1581) [jetty-ee10-servlet-12.0.3.jar:?] at org.eclipse.jetty.ee10.servlet@12.0.3/org.eclipse.jetty.ee10.servlet.ServletHandler$MappedServlet.handle(ServletHandler.java:1542) [jetty-ee10-servlet-12.0.3.jar:?] at org.eclipse.jetty.ee10.servlet@12.0.3/org.eclipse.jetty.ee10.servlet.ServletChannel.dispatch(ServletChannel.java:886) [jetty-ee10-servlet-12.0.3.jar:?] at org.eclipse.jetty.ee10.servlet@12.0.3/org.eclipse.jetty.ee10.servlet.ServletChannel.handle(ServletChannel.java:491) [jetty-ee10-servlet-12.0.3.jar:?] at org.eclipse.jetty.ee10.servlet@12.0.3/org.eclipse.jetty.ee10.servlet.ServletHandler.handle(ServletHandler.java:463) [jetty-ee10-servlet-12.0.3.jar:?] at org.eclipse.jetty.security@12.0.3/org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:571) [jetty-security-12.0.3.jar:?] at org.eclipse.jetty.ee10.servlet@12.0.3/org.eclipse.jetty.ee10.servlet.SessionHandler.handle(SessionHandler.java:693) [jetty-ee10-servlet-12.0.3.jar:?] at org.eclipse.jetty.server@12.0.3/org.eclipse.jetty.server.handler.ContextHandler.handle(ContextHandler.java:809) [jetty-server-12.0.3.jar:?] at org.eclipse.jetty.server@12.0.3/org.eclipse.jetty.server.Server.handle(Server.java:179) [jetty-server-12.0.3.jar:?] at org.eclipse.jetty.server@12.0.3/org.eclipse.jetty.server.internal.HttpChannelState$HandlerInvoker.run(HttpChannelState.java:649) [jetty-server-12.0.3.jar:?] at org.eclipse.jetty.server@12.0.3/org.eclipse.jetty.server.internal.HttpConnection.onFillable(HttpConnection.java:471) [jetty-server-12.0.3.jar:?] at org.eclipse.jetty.io@12.0.3/org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:322) [jetty-io-12.0.3.jar:?] at org.eclipse.jetty.io@12.0.3/org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:100) [jetty-io-12.0.3.jar:?] at org.eclipse.jetty.io@12.0.3/org.eclipse.jetty.io.SelectableChannelEndPoint$1.run(SelectableChannelEndPoint.java:53) [jetty-io-12.0.3.jar:?] at org.eclipse.jetty.util@12.0.3/org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:971) [jetty-util-12.0.3.jar:?] at org.eclipse.jetty.util@12.0.3/org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.doRunJob(QueuedThreadPool.java:1196) [jetty-util-12.0.3.jar:?] at org.eclipse.jetty.util@12.0.3/org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1151) [jetty-util-12.0.3.jar:?] at java.base/java.lang.Thread.run(Thread.java:833) [?:?]
解决方案
核心问题分析
- API包名变更:Jersey 3.x基于Jakarta EE 9,所有API包名从
javax.ws.rs改为jakarta.ws.rs,原初始化参数javax.ws.rs.Application已失效,导致Jersey无法找到并初始化RestApplication,这也是构造函数日志未打印的直接原因。 - 路径叠加冲突:
RestApplication上的@ApplicationPath("rest")与Servlet映射的/rest/*叠加,实际访问路径变为/rest/rest/foo/temp,和你访问的路径不匹配。
修复步骤
- 修正初始化参数名
将WebInitializer中Jersey的初始化参数从javax.ws.rs.Application改为jakarta.ws.rs.Application:
jerseyRegistration.setInitParameter("jakarta.ws.rs.Application", RestApplication.class.getName());
调整路径配置(二选一)
- 方案一:移除
@ApplicationPath注解
删除RestApplication类上的@ApplicationPath("rest"),保持Servlet映射的/rest/*不变,此时访问http://127.0.0.1:8080/rest/foo/temp即可正确匹配。 - 方案二:修改Servlet映射路径
保留@ApplicationPath("rest"),将Servlet映射改为/*,同时调整Spring DispatcherServlet的映射为/或特定前缀(避免拦截Jersey请求),此时访问路径仍为http://127.0.0.1:8080/rest/foo/temp。
- 方案一:移除
验证初始化状态
重启应用后,检查是否打印CLASSES REGISTERED IN JERSEY日志,确认Jersey应用已正确初始化。
内容的提问来源于stack exchange,提问作者user5182503
相关产品推荐
相关产品推荐

