Spring Boot 2.7.10中如何修改WebSocketGraphQlClient订阅消息类型为start?
解决WebSocketGraphQlClient订阅消息类型不匹配问题
问题背景
使用Spring Boot 2.7.10的WebSocketGraphQlClient执行订阅时,客户端发送的消息类型为subscribe,但服务器期望start类型,导致返回Invalid message type!错误。用Insomnia发送start类型消息可正常工作,日志显示客户端编码的消息类型确实为subscribe。
原因分析
Spring的WebSocketGraphQlClient默认遵循GraphQL over WebSocket Protocol(graphql-ws),该协议中订阅消息类型为subscribe;而你的服务器可能使用的是旧版的Apollo subscriptions-transport-ws协议,该协议中订阅消息类型为start。两者的消息类型枚举不兼容,直接修改通用Jackson序列化器无法生效,因为涉及到WebSocketGraphQlClient.GraphQlWebSocketMessage.Type这个内部枚举类的序列化逻辑。
解决方案
通过自定义Jackson序列化器,将枚举类型SUBSCRIBE映射为字符串start,并在构建WebSocketGraphQlClient时配置该序列化器:
1. 编写自定义枚举序列化器
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import org.springframework.graphql.client.WebSocketGraphQlClient; import java.io.IOException; public class GraphQlWsTypeSerializer extends JsonSerializer<WebSocketGraphQlClient.GraphQlWebSocketMessage.Type> { @Override public void serialize(WebSocketGraphQlClient.GraphQlWebSocketMessage.Type type, JsonGenerator gen, SerializerProvider serializers) throws IOException { // 将SUBSCRIBE替换为start,其他类型保持原小写形式 if (WebSocketGraphQlClient.GraphQlWebSocketMessage.Type.SUBSCRIBE.equals(type)) { gen.writeString("start"); } else { gen.writeString(type.name().toLowerCase()); } } }
2. 构建带自定义编码器的WebSocketGraphQlClient
import org.springframework.graphql.client.WebSocketGraphQlClient; import org.springframework.http.codec.json.Jackson2JsonEncoder; import com.fasterxml.jackson.databind.module.SimpleModule; import org.springframework.web.reactive.socket.client.ReactorNettyWebSocketClient; // 初始化WebSocket连接器 ReactorNettyWebSocketClient clientWebSocketConnector = new ReactorNettyWebSocketClient(); // 注册自定义序列化器到Jackson模块 SimpleModule module = new SimpleModule(); module.addSerializer(WebSocketGraphQlClient.GraphQlWebSocketMessage.Type.class, new GraphQlWsTypeSerializer()); // 创建自定义编码器并注册模块 Jackson2JsonEncoder customEncoder = new Jackson2JsonEncoder(); customEncoder.getObjectMapper().registerModule(module); // 构建配置好的WebSocketGraphQlClient WebSocketGraphQlClient client = WebSocketGraphQlClient.builder("ws://your-server-endpoint/graphql", clientWebSocketConnector) .encoder(customEncoder) .build();
3. 使用修改后的客户端执行订阅
client.document("subscription onCommentsAdded { comment}") .executeSubscription() .subscribe( response -> System.out.println("收到订阅消息: " + response.getData()), error -> System.err.println("订阅出错: " + error.getMessage()) );
修改后,客户端发送的订阅消息类型会被替换为start,匹配服务器的要求。
内容的提问来源于stack exchange,提问作者vedpathak supriya
相关产品推荐
相关产品推荐

