StompFrameHandler 没有从消息中获取有效负载
Posted
技术标签:
【中文标题】StompFrameHandler 没有从消息中获取有效负载【英文标题】:StompFrameHandler doesn't get payload from message 【发布时间】:2018-01-29 13:16:03 【问题描述】:最后,我的 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 返回的类型 - 我选择字符串,因为我认为每条消息都可以呈现为字符串。
【问题讨论】:
仍在努力解决这个问题。有什么想法吗? 【参考方案1】:我也有类似的问题。
问题是我指定了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())
来做到这一点。
【讨论】:
你拯救了我的一天,我使用了这一行 new String((byte[]) message.getPayload()) 并且我能够进行自定义实现,谢谢【参考方案2】:我明白你的意思,你需要扩展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
是您要转换流数据的用户定义类
开始了!!
【讨论】:
【参考方案3】:我分享我的实现,希望有用。 我没有设置消息转换器,而是自定义实现了方法 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());
【讨论】:
【参考方案4】:需要定义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;**
...
【讨论】:
以上是关于StompFrameHandler 没有从消息中获取有效负载的主要内容,如果未能解决你的问题,请参考以下文章
为啥我们要包装 HttpServletRequest ? api 提供了一个 HttpServletRequestWrapper 但我们从包装请求中获得了啥?