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

时间:2018-01-29 13:16:04

标签: java websocket spring-websocket

最后我将我的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());

Stomp Frame Handler:

    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返回的Type - 我选择String,因为我认为每条消息都可以表示为字符串。

4 个答案:

答案 0 :(得分:0)

我有一个类似的问题。

问题是我指定了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())来实现。

答案 1 :(得分: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是您要转换流数据的用户定义的类

好去!

答案 2 :(得分:0)

我分享我的实现方式,希望对您有所帮助。 我没有设置messageconverter,而是对方法 handleFrame

进行了自定义实现
<link to='path' />
<a href='path' 

,然后处理发送的消息(在我的情况下为JSON字符串对象)

    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();

答案 3 :(得分: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;**
    }
...
}