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

Jetty嵌入式UberJar部署双WAR时WebSocket无升级工厂问题

问题分析与解决方案

没错,你遇到的问题核心就是缺少WebSocket升级工厂的配置。从日志里的No factory for Upgrade: websocket就能看出来——Jetty的连接器找不到处理WebSocket升级请求的对应工厂,导致无法将HTTP请求升级为WebSocket连接。

在嵌入式Jetty环境中,WebSocket支持不会自动为WebAppContext启用,哪怕你的WAR包里已经包含了WebSocket端点代码。尤其是当你部署多个WAR包时,需要单独为需要WebSocket功能的上下文手动配置支持。

下面分两种常见场景给出解决方案:

场景1:使用JSR-356标准WebSocket API(@ServerEndpoint注解)

如果你的WAR包是用标准的@ServerEndpoint注解实现WebSocket的,只需要在创建hubContext后添加WebSocket容器初始化配置即可:

// 为带WebSocket的hubContext启用JSR-356支持
JavaxWebSocketServletContainerInitializer.configure(hubContext, (servletContext, wsContainer) -> {
    // 可选:配置WebSocket容器参数,比如最大消息缓冲区大小
    wsContainer.setDefaultMaxTextMessageBufferSize(1024 * 1024);
    wsContainer.setDefaultMaxBinaryMessageBufferSize(1024 * 1024);
    
    // 如果WAR包没有自动扫描@ServerEndpoint(比如缺少web-fragment.xml),可以手动注册端点
    // wsContainer.addEndpoint(YourWebSocketEndpoint.class);
});

这段代码会自动为hubContext注册WebSocket升级工厂,让Jetty能够识别并处理Upgrade: websocket请求。

场景2:使用Jetty原生WebSocket API

如果你的WAR包用的是Jetty原生的WebSocket实现(比如继承WebSocketServlet或使用WebSocketCreator),需要确保你在WAR的web.xml中配置了对应的Servlet,或者在嵌入式代码中为hubContext添加ServletHolder:

// 假设你的原生WebSocket Servlet是MyJettyWebSocketServlet
ServletHolder wsServletHolder = new ServletHolder(new MyJettyWebSocketServlet());
hubContext.addServlet(wsServletHolder, "/your-websocket-path/*");

完整修改后的代码示例

public static void main(String[] args) throws Exception {
    Server server = new Server();
    ServerConnector connector = new ServerConnector(server);
    connector.setPort(9191); // 显式指定端口更清晰
    server.setConnectors(new Connector[]{connector});

    // war #1 - 普通Web应用
    WebAppContext portalContext = new WebAppContext();
    portalContext.setContextPath("/portal");
    portalContext.setWar("/path/to/war/file/app1.war");

    // war #2 - 带WebSocket的应用
    WebAppContext hubContext = new WebAppContext();
    hubContext.setContextPath("/hub");
    hubContext.setWar("/path/to/war/file/app2.war");

    // 启用JSR-356 WebSocket支持(根据你的实际场景选择)
    JavaxWebSocketServletContainerInitializer.configure(hubContext, (servletContext, wsContainer) -> {
        wsContainer.setDefaultMaxTextMessageBufferSize(1024 * 1024);
        wsContainer.setDefaultMaxBinaryMessageBufferSize(1024 * 1024);
    });

    HandlerCollection handlerCollection = new HandlerCollection();
    handlerCollection.setHandlers(new Handler[]{hubContext, portalContext});
    server.setHandler(handlerCollection);

    try {
        server.start();
        System.out.println("Server running at http://localhost:" + connector.getPort());
        System.in.read();
        server.stop();
        server.join();
    } catch (Exception e) {
        e.printStackTrace();
        System.exit(100);
    }
}

额外注意:依赖检查

确保你的项目依赖中包含了Jetty WebSocket的相关库,以Maven为例:

<!-- JSR-356 API -->
<dependency>
    <groupId>javax.websocket</groupId>
    <artifactId>javax.websocket-api</artifactId>
    <version>1.1</version>
    <scope>provided</scope>
</dependency>
<!-- Jetty WebSocket Server实现 -->
<dependency>
    <groupId>org.eclipse.jetty.websocket</groupId>
    <artifactId>websocket-server</artifactId>
    <version>${jetty.version}</version>
</dependency>
<dependency>
    <groupId>org.eclipse.jetty.websocket</groupId>
    <artifactId>javax-websocket-server-impl</artifactId>
    <version>${jetty.version}</version>
</dependency>

替换${jetty.version}为你实际使用的Jetty版本(比如9.4.50.v20221201或11.0.15)。

完成以上配置后,重启服务器,WebSocket连接应该就能正常工作了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 06:17:29