嵌入 Jetty 10 的 GraphQL 订阅
Posted
技术标签:
【中文标题】嵌入 Jetty 10 的 GraphQL 订阅【英文标题】:GraphQL subscription with Jetty 10 embedded 【发布时间】:2021-11-11 09:54:44 【问题描述】:我的目标是让最新的 Graphql-java 的功能版本与 jetty 版本 10 混合。
我已经使用不同的方法做了很多测试,现在我被 9.4 和 10.0.6 版本之间的 WebSocket 实现(在 Jetty 上)的差异所困扰。
为了测试实现,我正在处理来自graphQL repository sample 的示例。
我的测试是在子项目 servlet-hello-world
上完成的,其中完成了一个简单的 graphQL 订阅并在 jetty 9.4 上工作
我已更新 gradle 以使用最新版本
def jettyVersion = '9.4.43.v20210629'
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"
implementation "org.eclipse.jetty.websocket:websocket-api:$jettyVersion"
implementation "org.eclipse.jetty.websocket:websocket-server:$jettyVersion"
implementation "org.eclipse.jetty.websocket:javax-websocket-server-impl:$jettyVersion"
implementation "org.eclipse.jetty.websocket:websocket-common:$jettyVersion"
到
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"
implementation "org.eclipse.jetty.websocket:websocket-jetty-api:$jettyVersion"
implementation "org.eclipse.jetty.websocket:websocket-jetty-server:$jettyVersion"
// implementation "org.eclipse.jetty.websocket:javax-websocket-server-impl:$jettyVersion"
// implementation "org.eclipse.jetty.websocket:websocket-common:$jettyVersion"
然后我被困在 API 的变化上,其中 WebSocketServletContainerInitalizer 被 JettyWebSocketServletContainerInitializer 替换:
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);
WebSocketServerContainerInitializer.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();
不同之处在于配置器已将配置器的类型从 ServletContainer
更改为 JettyWebSocketServerContainer
,并且不再有 addEndpoint 方法可以连接我的 SubscriptionEndpoint。
我完全不知道如何连接我的GraphQLWebsocketServlet
。
【问题讨论】:
【参考方案1】:旧版本的 Jetty 是 websocket 实现中立的(核心、javax.websocket、jetty 原生 websocket 等)。当同时使用多个实现时,这被证明太复杂了。
新的 Jetty 10+ 实施要求您为正在使用的实施使用适当的 <Impl>WebSocketServletContainerInitializer
。 (其中<Impl>
是Javax
、Jakarta
或Jetty
之一)
由于您使用的是javax.websocket
,因此这里是要使用的适当类。
JavaxWebSocketServletContainerInitializer.configure(context, (servletContext, wsContainer) ->
// This lambda will be called at the appropriate place in the
// ServletContext initialization phase where you can initialize
// and configure your websocket container.
// Configure defaults for container
wsContainer.setDefaultMaxTextMessageBufferSize(65535);
// Add WebSocket endpoint to javax.websocket layer
wsContainer.addEndpoint(
ServerEndpointConfig.Builder.create(
SubscriptionEndpoint.class, "/subscriptions")
.configurator(new GraphQLWSEndpointConfigurer())
.build());
);
【讨论】:
谢谢你,解决方案就是这么简单,但是我没有找到任何迁移指南,Jetty 文档在 Websocket 实现章节上只是说“TODO”;) 我刚用github.com/jetty-project/embedded-jetty-websocket-examples/tree/…以上是关于嵌入 Jetty 10 的 GraphQL 订阅的主要内容,如果未能解决你的问题,请参考以下文章
Apollo GraphQL:MQTT 订阅代理以仅提供已发布的数据
Jetty 9.0 嵌入了带有 SPDY 但没有 SSL/NPN 的配置