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

嵌入式Jetty 10搭配graphql-java实现GraphQL subscription适配问题

Jetty 10 整合 graphql-java WebSocket 端点配置解决方案

方案一:保留原有JSR356端点配置(改造成本最低)

Jetty 10 全面切换到Jakarta EE 9命名空间,原javax.websocket相关实现已迁移到jakarta.websocket包下,你之前注释掉的JSR356实现依赖需要替换为对应Jakarta版本,不需要改用Jetty原生WebSocket API。

调整依赖配置

def jettyVersion = '10.0.6'
dependencies {
    implementation "com.graphql-java-kickstart:graphql-java-servlet:$LIB_GRAPHQL_SERVLET_VER"
    implementation "io.projectreactor:reactor-core:3.4.9"
    implementation 'ch.qos.logback:logback-classic:1.2.5'
    implementation 'org.slf4j:slf4j-simple:2.0.0-alpha4'
    implementation "org.eclipse.jetty:jetty-webapp:${jettyVersion}"
    implementation "org.eclipse.jetty:jetty-annotations:${jettyVersion}"
    // 替换原javax-websocket-server-impl为Jakarta版本实现
    implementation "org.eclipse.jetty.websocket:websocket-jakarta-server:${jettyVersion}"
}

修改服务启动配置

将原WebSocketServerContainerInitializer替换为Jakarta版本的初始化类,原有addEndpoint逻辑完全不需要修改:

import org.eclipse.jetty.websocket.jakarta.server.config.JakartaWebSocketServerContainerInitializer;

// 原有服务启动代码保持不变
var server = new Server();
var connector = new ServerConnector(server);
connector.setPort(PORT);
server.addConnector(connector);

var context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
context.addServlet(HelloServlet.class, "/graphql");
server.setHandler(context);

// 仅替换初始化类,其余配置逻辑不变
JakartaWebSocketServerContainerInitializer.configure(
    context,
    (servletContext, serverContainer) ->
        serverContainer.addEndpoint(
            ServerEndpointConfig.Builder.create(SubscriptionEndpoint.class, "/subscriptions")
                .configurator(new GraphQLWSEndpointConfigurer())
                .build()));

server.setHandler(context);

server.start();
server.dump(System.err);
server.join();

方案二:适配Jetty 10原生WebSocket API

如果要使用Jetty原生WebSocket API,不需要依赖JSR356实现,直接将GraphQLWebsocketServlet包装为Jetty原生WebSocket Servlet注册即可:

自定义Jetty WebSocket Servlet

import org.eclipse.jetty.websocket.server.JettyWebSocketServlet;
import org.eclipse.jetty.websocket.server.JettyWebSocketServletFactory;
import javax.servlet.ServletException;

public class GraphQLJettyWebSocketServlet extends JettyWebSocketServlet {
    private final GraphQLWebsocketServlet delegate;

    public GraphQLJettyWebSocketServlet(GraphQLWebsocketServlet delegate) {
        this.delegate = delegate;
    }

    @Override
    protected void configure(JettyWebSocketServletFactory factory) {
        factory.addMapping("/subscriptions", (upgradeRequest, upgradeResponse) -> delegate);
    }

    // 按需重写init/destroy方法透传到delegate
    @Override
    public void init() throws ServletException {
        delegate.init(getServletConfig());
        super.init();
    }

    @Override
    public void destroy() {
        delegate.destroy();
        super.destroy();
    }
}

修改服务启动配置

删除原有WebSocketServerContainerInitializer配置逻辑,直接注册自定义的Servlet:

var server = new Server();
var connector = new ServerConnector(server);
connector.setPort(PORT);
server.addConnector(connector);

var context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
context.addServlet(HelloServlet.class, "/graphql");
// 注册GraphQL WebSocket处理Servlet
context.addServlet(new ServletHolder(new GraphQLJettyWebSocketServlet(yourGraphQLWebsocketServletInstance)), "/subscriptions/*");

server.setHandler(context);

server.start();
server.dump(System.err);
server.join();

注意事项

  • 若使用方案一,需确保你的graphql-java-servlet版本支持Jakarta EE 9命名空间,否则会出现javax.websocket类找不到的异常,可升级到最新版本的graphql-java-servlet解决该问题。
  • Jetty 10 不再支持javax.websocket命名空间的实现,请勿混用Jetty9和Jetty10的WebSocket依赖。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 22:24:04