You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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) [?:?]
解决方案

核心问题分析

  1. API包名变更:Jersey 3.x基于Jakarta EE 9,所有API包名从javax.ws.rs改为jakarta.ws.rs,原初始化参数javax.ws.rs.Application已失效,导致Jersey无法找到并初始化RestApplication,这也是构造函数日志未打印的直接原因。
  2. 路径叠加冲突:RestApplication上的@ApplicationPath("rest")与Servlet映射的/rest/*叠加,实际访问路径变为/rest/rest/foo/temp,和你访问的路径不匹配。

修复步骤

  1. 修正初始化参数名
    将WebInitializer中Jersey的初始化参数从javax.ws.rs.Application改为jakarta.ws.rs.Application:
jerseyRegistration.setInitParameter("jakarta.ws.rs.Application", RestApplication.class.getName());
  1. 调整路径配置(二选一)

    • 方案一:移除@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。
  2. 验证初始化状态
    重启应用后,检查是否打印CLASSES REGISTERED IN JERSEY日志,确认Jersey应用已正确初始化。

内容的提问来源于stack exchange,提问作者user5182503

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 04:37:32