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

GraphQL SPQR搭配Spring Reactive实现订阅时WebSocket连接报错如何解决

问题排查与解决思路

1. 移除不兼容的WebSocket依赖

你当前使用Webflux+Netty的响应式技术栈,引入的spring-boot-starter-websocket是Servlet容器专用的WebSocket依赖,和Netty栈完全不兼容,直接从build.gradle中删除该依赖即可,Webflux本身已经内置WebSocket支持,无需额外引入独立starter。

2. 手动配置Webflux下的GraphQL订阅端点

你使用的graphql-spqr-spring-boot-starter 0.0.6版本默认仅自动配置Servlet栈的订阅端点,Webflux场景下需要手动注册WebSocket路由,新增如下配置类即可:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.web.reactive.HandlerMapping;
import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping;
import org.springframework.web.reactive.socket.server.support.WebSocketHandlerAdapter;
import graphql.GraphQL;
import io.leangen.graphql.spqr.spring.web.reactive.GraphQLWebSocketHandler;
import io.leangen.graphql.spqr.spring.web.ws.GraphQLWsProtocolFactory;
import java.util.Map;

@Configuration
public class GraphQLWsConfig {
    private final GraphQL graphQL;

    public GraphQLWsConfig(GraphQL graphQL) {
        this.graphQL = graphQL;
    }

    @Bean
    public HandlerMapping graphQLWsHandlerMapping() {
        GraphQLWebSocketHandler wsHandler = new GraphQLWebSocketHandler(
                graphQL, new GraphQLWsProtocolFactory().create()
        );
        SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
        mapping.setUrlMap(Map.of("/subscriptions", wsHandler));
        mapping.setOrder(Ordered.HIGHEST_PRECEDENCE);
        return mapping;
    }

    @Bean
    public WebSocketHandlerAdapter webSocketHandlerAdapter() {
        return new WebSocketHandlerAdapter();
    }
}

3. 修正Playground订阅端点配置

graphql-kickstart playground默认不会自动识别Webflux下的订阅端点,需要在配置文件中手动指定:

# application.yml
graphql:
  playground:
    enabled: true
    endpoint: /graphql
    subscription-endpoint: /subscriptions

如果你的项目配置了server.webflux.base-path前缀,需要把前缀同步加到subscription-endpoint的路径中。

4. 补充订阅触发逻辑

你当前仅定义了订阅的Publisher,还需要在数据变更的Mutation逻辑中,主动向匹配的订阅者推送数据,示例如下:

@GraphQLMutation
public Mono<ProductDto> saveProduct(ProductDto productDto) {
    return productRepository.save(AppUtils.ProductDtoToEntity(productDto))
            .map(AppUtils::ProductEntityToDto)
            .doOnSuccess(savedProduct -> {
                // 向价格匹配的所有订阅者推送新增/修改的商品数据
                subscribers.get(savedProduct.getPrice())
                        .forEach(sink -> sink.next(savedProduct));
            });
}

额外校验点

  • 确认启动端口无占用,启动后可直接测试WebSocket地址连通性,排查网络或路径配置问题
  • 你当前使用的Spring Boot 2.5.4和SPQR starter 0.0.6版本兼容,无需调整版本号

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 06:42:01