如何使用和自定义 MessageConversion(Spring websocket client)
how to use and customize MessageConversion(Spring websocket client)
我用 spring 编写了一个网络套接字服务器和一个客户端。代码如下。向服务器发送消息的代码有效,但 sesssion.subscribe 方法无法从服务器接收消息。我搜索了许多文档并检查了我的代码。我不明白为什么它不能工作。
这是我的客户代码:
public class Test {
public static void main(String[] args) {
Thread thread = new Thread(new WebsocketThread());
thread.start();
Thread.sleep(5000);
}
}
class MyStompSessionHandler extends StompSessionHandlerAdapter {
@Override
public void afterConnected(StompSession session, StompHeaders connectedHeaders) {
session.send("/app/messages", "{'payload3':2222}".getBytes());
session.subscribe("/user/queue/position-updates", new StompFrameHandler() {
@Override
public Type getPayloadType(StompHeaders headers) {
return String.class;
}
@Override
public void handleFrame(StompHeaders headers, Object payload) {
System.out.println("test:" + payload);
}
});
}
}
class WebsocketThread implements Runnable{
@Override
public void run() {
List<Transport> transports = new ArrayList<>(1);
transports.add(new WebSocketTransport( new StandardWebSocketClient()) );
WebSocketClient webSocketClient = new SockJsClient(transports);
WebSocketStompClient stompClient = new WebSocketStompClient(webSocketClient);
String url = "ws://127.0.0.1:8860/orders";
StompSessionHandler sessionHandler = new MyStompSessionHandler();
ListenableFuture<StompSession> future = stompClient.connect(url, sessionHandler);
}
}
这是我的服务器代码:
@Controller
public class TestController {
@Autowired
private SimpMessagingTemplate simpMessagingTemplate;
@MessageMapping("/messages")
public void sendUserMsg(String messages) throws IOException {
System.out.println("webSocket:" + messages);
simpMessagingTemplate.convertAndSend("/queue/position-updates", "This is return message");
}
}
这是例外:
org.springframework.messaging.converter.MessageConversionException: 没有合适的转换器,payloadType=class java.lang.String, handlerType=class com.example.hello.MyStompSessionHandler
在 org.springframework.messaging.simp.stomp.DefaultStompSession.invokeHandler(DefaultStompSession.java:419)
在 org.springframework.messaging.simp.stomp.DefaultStompSession.handleMessage(DefaultStompSession.java:373)
在 org.springframework.web.socket.messaging.WebSocketStompClient$WebSocketTcpConnectionHandlerAdapter.handleMessage(WebSocketStompClient.java:342)
在 org.springframework.web.socket.sockjs.client.AbstractClientSockJsSession.handleMessageFrame(AbstractClientSockJsSession.java:267)
在 org.springframework.web.socket.sockjs.client.AbstractClientSockJsSession.handleFrame(AbstractClientSockJsSession.java:200)
在 org.springframework.web.socket.sockjs.client.WebSocketTransport$ClientSockJsWebSocketHandler.handleTextMessage(WebSocketTransport.java:162)
在 org.springframework.web.socket.handler.AbstractWebSocketHandler.handleMessage(AbstractWebSocketHandler.java:43)
在 org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.handleTextMessage(StandardWebSocketHandlerAdapter.java:110)
在 org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.access000 美元(StandardWebSocketHandlerAdapter.java:42)
在 org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$3.onMessage(StandardWebSocketHandlerAdapter.java:81)
在 org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$3.onMessage(StandardWebSocketHandlerAdapter.java:78)
在 org.apache.tomcat.websocket.WsFrameBase.sendMessageText(WsFrameBase.java:399)
在 org.apache.tomcat.websocket.WsFrameBase.processDataText(WsFrameBase.java:500)
在 org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:295)
在 org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:131)
在 org.apache.tomcat.websocket.WsFrameClient.processSocketRead(WsFrameClient.java:73)
在 org.apache.tomcat.websocket.WsFrameClient.access300 美元(WsFrameClient.java:31)
在 org.apache.tomcat.websocket.WsFrameClient$WsFrameClientCompletionHandler.completed(WsFrameClient.java:131)
在 org.apache.tomcat.websocket.WsFrameClient$WsFrameClientCompletionHandler.completed(WsFrameClient.java:114)
在 sun.nio.ch.Invoker.invokeUnchecked(Invoker.java:126)
在 sun.nio.ch.Invoker$2.run(Invoker.java:218)
在 sun.nio.ch.AsynchronousChannelGroupImpl$1.run(AsynchronousChannelGroupImpl.java:112)
在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
在 java.lang.Thread.run(Thread.java:745)
您似乎没有在 Web 套接字配置中配置任何 org.springframework.messaging.converter.MessageConverter。
如果您的 class 路径上有 jackson jar,那么它将被自动拾取以进行 json 转换。对于其他转换器,您需要在 WebSocket Config 文件中进行配置。
@Configuration
@EnableWebSocketMessageBroker
@ComponentScan(SpringScanPackageNames)
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public boolean configureMessageConverters(List<MessageConverter> arg0) {
StringMessageConverter strConvertor = new StringMessageConverter();
arg0.add(strConvertor);
return true;
}
// Other config
给客户端添加一个StringMessageConverter,成功了。
WebSocketStompClient stompClient = new WebSocketStompClient(webSocketClient);
stompClient.setMessageConverter(new StringMessageConverter());
但是如何自定义我们自己的MessageConverter呢?有文章吗?
给客户端添加一个SimpleMessageConverter,成功了。
stompClient.setMessageConverter(new SimpleMessageConverter());
我有一个类似的问题(尽管我发送的是自定义对象),对我有用的是简单地将 Jackson2Message 消息转换器设置为
webSocketStompClient.messageConverter = new MappingJackson2MessageConverter()
我在以下位置找到了关于此的有用信息(和示例):https://github.com/Noozen/spring-boot-websocket-client#the-java-client
我用 spring 编写了一个网络套接字服务器和一个客户端。代码如下。向服务器发送消息的代码有效,但 sesssion.subscribe 方法无法从服务器接收消息。我搜索了许多文档并检查了我的代码。我不明白为什么它不能工作。
这是我的客户代码:
public class Test {
public static void main(String[] args) {
Thread thread = new Thread(new WebsocketThread());
thread.start();
Thread.sleep(5000);
}
}
class MyStompSessionHandler extends StompSessionHandlerAdapter {
@Override
public void afterConnected(StompSession session, StompHeaders connectedHeaders) {
session.send("/app/messages", "{'payload3':2222}".getBytes());
session.subscribe("/user/queue/position-updates", new StompFrameHandler() {
@Override
public Type getPayloadType(StompHeaders headers) {
return String.class;
}
@Override
public void handleFrame(StompHeaders headers, Object payload) {
System.out.println("test:" + payload);
}
});
}
}
class WebsocketThread implements Runnable{
@Override
public void run() {
List<Transport> transports = new ArrayList<>(1);
transports.add(new WebSocketTransport( new StandardWebSocketClient()) );
WebSocketClient webSocketClient = new SockJsClient(transports);
WebSocketStompClient stompClient = new WebSocketStompClient(webSocketClient);
String url = "ws://127.0.0.1:8860/orders";
StompSessionHandler sessionHandler = new MyStompSessionHandler();
ListenableFuture<StompSession> future = stompClient.connect(url, sessionHandler);
}
}
这是我的服务器代码:
@Controller
public class TestController {
@Autowired
private SimpMessagingTemplate simpMessagingTemplate;
@MessageMapping("/messages")
public void sendUserMsg(String messages) throws IOException {
System.out.println("webSocket:" + messages);
simpMessagingTemplate.convertAndSend("/queue/position-updates", "This is return message");
}
}
这是例外:
org.springframework.messaging.converter.MessageConversionException: 没有合适的转换器,payloadType=class java.lang.String, handlerType=class com.example.hello.MyStompSessionHandler 在 org.springframework.messaging.simp.stomp.DefaultStompSession.invokeHandler(DefaultStompSession.java:419) 在 org.springframework.messaging.simp.stomp.DefaultStompSession.handleMessage(DefaultStompSession.java:373) 在 org.springframework.web.socket.messaging.WebSocketStompClient$WebSocketTcpConnectionHandlerAdapter.handleMessage(WebSocketStompClient.java:342) 在 org.springframework.web.socket.sockjs.client.AbstractClientSockJsSession.handleMessageFrame(AbstractClientSockJsSession.java:267) 在 org.springframework.web.socket.sockjs.client.AbstractClientSockJsSession.handleFrame(AbstractClientSockJsSession.java:200) 在 org.springframework.web.socket.sockjs.client.WebSocketTransport$ClientSockJsWebSocketHandler.handleTextMessage(WebSocketTransport.java:162) 在 org.springframework.web.socket.handler.AbstractWebSocketHandler.handleMessage(AbstractWebSocketHandler.java:43) 在 org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.handleTextMessage(StandardWebSocketHandlerAdapter.java:110) 在 org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.access000 美元(StandardWebSocketHandlerAdapter.java:42) 在 org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$3.onMessage(StandardWebSocketHandlerAdapter.java:81) 在 org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$3.onMessage(StandardWebSocketHandlerAdapter.java:78) 在 org.apache.tomcat.websocket.WsFrameBase.sendMessageText(WsFrameBase.java:399) 在 org.apache.tomcat.websocket.WsFrameBase.processDataText(WsFrameBase.java:500) 在 org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:295) 在 org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:131) 在 org.apache.tomcat.websocket.WsFrameClient.processSocketRead(WsFrameClient.java:73) 在 org.apache.tomcat.websocket.WsFrameClient.access300 美元(WsFrameClient.java:31) 在 org.apache.tomcat.websocket.WsFrameClient$WsFrameClientCompletionHandler.completed(WsFrameClient.java:131) 在 org.apache.tomcat.websocket.WsFrameClient$WsFrameClientCompletionHandler.completed(WsFrameClient.java:114) 在 sun.nio.ch.Invoker.invokeUnchecked(Invoker.java:126) 在 sun.nio.ch.Invoker$2.run(Invoker.java:218) 在 sun.nio.ch.AsynchronousChannelGroupImpl$1.run(AsynchronousChannelGroupImpl.java:112) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 在 java.lang.Thread.run(Thread.java:745)
您似乎没有在 Web 套接字配置中配置任何 org.springframework.messaging.converter.MessageConverter。 如果您的 class 路径上有 jackson jar,那么它将被自动拾取以进行 json 转换。对于其他转换器,您需要在 WebSocket Config 文件中进行配置。
@Configuration
@EnableWebSocketMessageBroker
@ComponentScan(SpringScanPackageNames)
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public boolean configureMessageConverters(List<MessageConverter> arg0) {
StringMessageConverter strConvertor = new StringMessageConverter();
arg0.add(strConvertor);
return true;
}
// Other config
给客户端添加一个StringMessageConverter,成功了。
WebSocketStompClient stompClient = new WebSocketStompClient(webSocketClient);
stompClient.setMessageConverter(new StringMessageConverter());
但是如何自定义我们自己的MessageConverter呢?有文章吗?
给客户端添加一个SimpleMessageConverter,成功了。
stompClient.setMessageConverter(new SimpleMessageConverter());
我有一个类似的问题(尽管我发送的是自定义对象),对我有用的是简单地将 Jackson2Message 消息转换器设置为
webSocketStompClient.messageConverter = new MappingJackson2MessageConverter()
我在以下位置找到了关于此的有用信息(和示例):https://github.com/Noozen/spring-boot-websocket-client#the-java-client