StompFrameHandler 未从消息中获取有效负载

问题描述 投票:0回答:5

最后,我的 websocket 客户端连接到端点,但我无法提取消息负载。 我可以获取标头,但无法识别有效负载。

我的 WebSocket 客户端如下所示:

    WebSocketTransport webSocketTransport = new WebSocketTransport(standardWebSocketClient);
    SockJsClient sockJsClient = new SockJsClient(Arrays.asList(webSocketTransport));
    WebSocketStompClient stompClient = new WebSocketStompClient(sockJsClient);

    stompClient.setMessageConverter(new StringMessageConverter());

    StompSessionHandler sessionHandler = new MyStompSessionHandler();
    ListenableFuture<StompSession> connect = stompClient.connect(URL, sessionHandler);

        StompSession stompSession = connect.get();
        System.out.println("sessionId: " + stompSession.getSessionId());

        String path = "/queue/orders";

        stompSession.subscribe(path, new MySimpleStompFrameHandler());

跺脚框架处理器:

    private class MySimpleStompFrameHandler implements StompFrameHandler {

    @Override
    public Type getPayloadType(StompHeaders stompHeaders) {
        System.out.println("Headers " + stompHeaders.toString());
        return String.class;
    }

    @Override
    public void handleFrame(StompHeaders stompHeaders, Object payload) {
        System.out.println("Msg " + payload.toString());
        completableFuture.complete(payload.toString());
    }
}

我在终端中写入了标题,但handleFrame 方法中没有任何内容。 有什么想法吗?

编辑: 调试后,我发现问题出在 DefaultStompSession 类中,该类使用我的frameHandler实现

    private void invokeHandler(StompFrameHandler handler, Message<byte[]> message, StompHeaders stompHeaders) {
    if (message.getPayload().length == 0) {
        handler.handleFrame(stompHeaders, null);
        return;
    }
    Type type = handler.getPayloadType(stompHeaders);
    Class<?> payloadType = ResolvableType.forType(type).resolve();
    Object object = getMessageConverter().fromMessage(message, payloadType);
    if (object == null) {
        throw new MessageConversionException("No suitable converter, payloadType=" + payloadType +
                ", handlerType=" + handler.getClass());
    }
    handler.handleFrame(stompHeaders, object);
}

问题出在这一行之后

Type type = handler.getPayloadType(stompHeaders);
之后不再执行任何操作,我的程序刚刚结束,因此handleFrame()甚至没有执行。 有什么问题吗?也许使用从 getPayloadType 返回的类型 - 我选择字符串,因为我认为每条消息都可以呈现为字符串。

java websocket spring-websocket
5个回答
8
投票

我也有类似的问题。

问题是我指定了

stompClient.setMessageConverter(new StringMessageConverter());
,而 JSON 作为有效负载传递。

解决方案(针对我的问题):

stompClient.setMessageConverter(new MappingJackson2MessageConverter());

您可以采取哪些措施来找到解决方案:

  • 触发异常时抛出(或记录)。对于您的情况,您应该在

    MyStompSessionHandler
    中添加以下方法的覆盖:

     @Override
     public void handleException(StompSession session, StompCommand command, StompHeaders headers, byte[] payload, Throwable exception) {
         throw new RuntimeException("Failure in WebSocket handling", exception);
     }
    
  • 调试时

    invokeHandler
    ,检查有效负载的内容。如果您能够执行代码,则可以通过执行
    new String((byte[]) message.getPayload())
    来完成此操作。


0
投票

我明白你的观点,你需要扩展

StompSessionHandlerAdapter
实施
StompFrameHandler

我为你尝试了一些东西:

public class MySimpleStompFrameHandler extends StompSessionHandlerAdapter implements StompFrameHandler {

private Logger logger = LogManager.getLogger(MyStompSessionHandler.class);

@Override
public void afterConnected(StompSession session, StompHeaders connectedHeaders) {
    System.out.println("Connected");
}

@Override
public void handleException(StompSession session, StompCommand command, StompHeaders 
 headers, byte[] payload, Throwable exception) {
    logger.error("Got an exception", exception);
}

@Override
public Type getPayloadType(StompHeaders headers) {
    return <payload_type>.class;
}

@Override
public void handleFrame(StompHeaders headers, Object payload) {
    <payload_type> msg = (<payload_type>) payload;
    System.out.println(msg);
    logger.info("Received : " + msg);
}

}

其中

payload_type
是您要转换流数据的用户定义类

很高兴出发!!


0
投票

我分享我的实现,希望有用。 我没有设置 messageconverter 并执行了方法 handleFrame

的自定义实现
    WebSocketClient client = new StandardWebSocketClient();
    WebSocketStompClient stompClient = new WebSocketStompClient(client);
    StompSessionHandler sessionHandler = new MyStompSessionHandler(prop);
    WebSocketHttpHeaders webSocketHttpHeaders = new WebSocketHttpHeaders();
    webSocketHttpHeaders.add("Authorization", "Bearer " + token);

    StompSession session = stompClient.connect(endpoint, webSocketHttpHeaders, sessionHandler).get();

然后处理发送的消息,在我的例子中是一个 JSON 字符串对象

    @Override
    public Type getPayloadType(StompHeaders headers) {
        return null;
    }

    @Override
    public void handleFrame(StompHeaders headers, Object payload) {
        String cadena = new String((byte[]) payload);
        JsonParser parser = new JsonParser();
        JsonObject obj = parser.parse(cadena).getAsJsonObject();
        System.out.println(obj.toString());
    }   

0
投票

需要定义MessageConverter,然后实现对象类型为JSON的方法getPayloadType

SockJsClient sockJsClient = new SockJsClient(transports);
WebSocketStompClient stompClient = new WebSocketStompClient(sockJsClient);
stompClient.setMessageConverter(**new MappingJackson2MessageConverter()**);

....

public class SockJsWebsocketSubscriptionHandler implements StompFrameHandler {
    @Override
    public Type getPayloadType(StompHeaders headers) {
        return **HelloMessage.class;**
    }
...
}

0
投票

仅扩展现有答案。当使用

stompClient.setMessageConverter(new MappingJackson2MessageConverter());
强制 jackson 序列化和反序列化类时,请检查要序列化的类是否正确,并且是否缺少默认构造函数、setter 和 getter,...如果没有,则行为如所描述在这个问题中:
getPayloadType
被执行,但
handleFrame
没有被执行。系统上没有显示任何错误(Websockets 的 TRACE 中仍然有日志),但客户端上没有收到任何信息。

© www.soinside.com 2019 - 2024. All rights reserved.