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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 06:51:00