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

嵌入式Jetty WebSocket服务器非根上下文配置失效问题求助

问题分析

你的核心问题出在上下文匹配顺序和WebSocket映射路径两个关键点:

  • 当WebSocket Servlet放在根上下文/时,它会优先匹配所有请求,导致后续的/*上下文DefaultServlet完全无法被触发。
  • 改成/ws上下文后,WebSocket的映射配置和客户端请求路径不匹配,进而导致连接失败。
解决方案

调整上下文配置顺序与WebSocket映射规则,修改后的完整代码如下:

public WebsocketServer(int port, Model model, SessionManager sessionManager) throws Exception {
    Server server = new Server(port);
    server.setRequestLog((request, response) -> log_.info("request {}", request));

    ContextHandlerCollection handlers = new ContextHandlerCollection();

    ServletContextHandler sch;

    // /model 上下文 - 保持原有逻辑不变
    sch = new ServletContextHandler();
    sch.setContextPath("/model");
    sch.addServlet(new ServletHolder(new ModelServlet(model)), "/");
    sch.setResourceBase("cfg");
    handlers.addHandler(sch);

    // /web 上下文 - 保持原有逻辑不变
    sch = new ServletContextHandler();
    sch.setContextPath("/web");
    sch.addServlet(DefaultServlet.class, "/*");
    sch.setResourceBase("cfg");
    sch.setWelcomeFiles(new String[]{"websocket.html"});
    handlers.addHandler(sch);

    // /ws 上下文 - 修正映射配置
    sch = new ServletContextHandler();
    sch.setContextPath("/ws"); // 设置为目标/ws上下文
    Servlet websocketServlet = new JettyWebSocketServlet() {
        @Override
        protected void configure(JettyWebSocketServletFactory factory) {
            // 映射上下文内所有路径,匹配客户端的ws://localhost:8080/ws请求
            factory.addMapping("/*", (req, res) -> {
                Session s = new Session(req);
                sessionManager.add(s);
                return s;
            });
        }
    };
    // 将Servlet映射覆盖整个/ws上下文
    sch.addServlet(new ServletHolder(websocketServlet), "/*");
    JettyWebSocketServletContainerInitializer.configure(sch, null);
    handlers.addHandler(sch);

    // 根上下文DefaultServlet - 放在最后处理未匹配的请求
    sch = new ServletContextHandler();
    sch.setContextPath("/"); // 改为标准根上下文
    sch.addServlet(DefaultServlet.class, "/*");
    sch.setResourceBase("cfg");
    handlers.addHandler(sch);

    server.setHandler(handlers);
    server.start();
}

关键修改说明

  1. WebSocket映射调整:

    • 将Servlet映射从"/"改为"/*",确保整个/ws上下文下的请求都能被WebSocket Servlet处理。
    • 将factory.addMapping("/")改为factory.addMapping("/*"),匹配客户端发起的ws://localhost:8080/ws请求。
  2. 上下文顺序优化:

    • 把具体路径的上下文(/model、/web、/ws)放在前面,根上下文的DefaultServlet放在最后,这样只有当请求不匹配前面的具体路径时,才会触发DefaultServlet,避免被前置上下文覆盖。
  3. 根上下文修正:

    • 将原来的"/*"上下文改为标准的"/"根上下文,符合Jetty的上下文匹配规则。

验证逻辑

客户端使用ws://localhost:8080/ws连接WebSocket时,请求会被/ws上下文的WebSocket Servlet处理;访问http://localhost:8080/web可正常加载网页,http://localhost:8080/model能正常访问ModelServlet,未匹配的请求则由根上下文的DefaultServlet处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 08:47:35