最后,我的 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 返回的类型 - 我选择字符串,因为我认为每条消息都可以呈现为字符串。
我也有类似的问题。
问题是我指定了
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())
来完成此操作。
我明白你的观点,你需要扩展
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
是您要转换流数据的用户定义类
很高兴出发!!
我分享我的实现,希望有用。 我没有设置 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());
}
需要定义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;**
}
...
}
仅扩展现有答案。当使用
stompClient.setMessageConverter(new MappingJackson2MessageConverter());
强制 jackson 序列化和反序列化类时,请检查要序列化的类是否正确,并且是否缺少默认构造函数、setter 和 getter,...如果没有,则行为如所描述在这个问题中: getPayloadType
被执行,但 handleFrame
没有被执行。系统上没有显示任何错误(Websockets 的 TRACE 中仍然有日志),但客户端上没有收到任何信息。