Spring Boot Websocket客户端连接非STOMP服务无法读取消息如何解决
解决方案
核心原因
你当前使用的WebSocketStompClient是针对STOMP子协议封装的客户端,目标服务没有实现STOMP协议的握手、帧解析逻辑,因此STOMP的连接回调、消息处理逻辑永远不会触发,所有STOMP相关的组件都无法适配当前场景。
改造步骤
1. 实现自定义原生WebSocket消息处理器
直接基于Spring提供的TextWebSocketHandler实现消息处理逻辑,无需STOMP封装:
import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.handler.TextWebSocketHandler; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import lombok.Data; @Slf4j public class CustomWsHandler extends TextWebSocketHandler { private final ObjectMapper objectMapper = new ObjectMapper(); // 连接成功回调 @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { log.info("WebSocket连接成功,sessionId:{}", session.getId()); // 如果服务端需要客户端发送订阅指令才推送消息,可在此处构造对应的指令消息发送 } // 接收消息回调 @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { String payload = message.getPayload(); // 解析通用消息结构 WsMessage<?> wsMessage = objectMapper.readValue(payload, new TypeReference<WsMessage<Object>>() {}); if ("PRICE".equals(wsMessage.getType())) { WsMessage<Price> priceMsg = objectMapper.readValue(payload, new TypeReference<WsMessage<Price>>() {}); log.info("收到价格消息:{}", priceMsg.getData()); // 后续业务逻辑 } else { WsMessage<Operations> opsMsg = objectMapper.readValue(payload, new TypeReference<WsMessage<Operations>>() {}); log.info("收到操作消息:{}", opsMsg.getData()); // 后续业务逻辑 } } // 连接异常回调 @Override public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { log.error("连接异常", exception); } // 连接关闭回调 @Override public void afterConnectionClosed(WebSocketSession session, org.springframework.web.socket.CloseStatus status) throws Exception { log.info("连接关闭,状态:{}", status); } // 通用消息外层结构 @Data public static class WsMessage<T> { private T data; private String type; } // 价格实体类 @Data public static class Price { private Double price; private String id; } }
2. 调整启动连接代码
使用原生StandardWebSocketClient分别连接两个独立的消息端点:
import org.springframework.web.socket.client.standard.StandardWebSocketClient; import java.util.Scanner; import lombok.extern.slf4j.Slf4j; @Slf4j public class WSClient { // 两个独立的WebSocket端点地址 private static final String OPS_URL = "ws://localhost:8080/operations"; private static final String PRICE_URL = "ws://localhost:8080/prices"; public static void main(String[] args) throws Exception { StandardWebSocketClient client = new StandardWebSocketClient(); // 连接操作消息端点 client.doHandshake(new CustomWsHandler(), OPS_URL).get(); log.info("操作消息端点连接完成"); // 连接价格消息端点 client.doHandshake(new CustomWsHandler(), PRICE_URL).get(); log.info("价格消息端点连接完成"); // 阻塞主线程保持连接 new Scanner(System.in).nextLine(); } }
3. 清理无用代码
你之前编写的MsgController是STOMP服务端的注解控制器,作为客户端使用时完全无用,直接删除即可;所有Stomp相关的类都可以移除。
注意事项
Operations实体类保持你现有定义即可,和Price类同理,只需要对应data字段内的结构- 如果服务端有心跳检测要求,可在
CustomWsHandler中添加心跳发送逻辑,避免连接被断开 - 如果需要断线重连,可在
afterConnectionClosed方法中添加重连逻辑
内容的提问来源于stack exchange,提问作者Jeredriq Demas
相关产品推荐
相关产品推荐

