如何使用和自定义 MessageConversion(Spring websocket 客户端)

Posted

技术标签:

【中文标题】如何使用和自定义 MessageConversion(Spring websocket 客户端)【英文标题】:how to use and customize MessageConversion(Spring websocket client) 【发布时间】:2017-01-12 03:52:23 【问题描述】:

我用spring写了一个web socket服务器和一个客户端。代码如下。向服务器发送消息的代码工作,但 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.access$000(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.access$300(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)

【问题讨论】:

我同时使用 session.subscribe("/user/queue/position-updates", ...) 和 session.subscribe("/queue/position-updates", ...)无法工作 这是个例外: 您似乎没有在 web socket 配置中配置任何 org.springframework.messaging.converter.MessageConverter。 【参考方案1】:

给客户端添加一个StringMessageConverter,就可以了。

WebSocketStompClient stompClient = new WebSocketStompClient(webSocketClient);
stompClient.setMessageConverter(new StringMessageConverter());

但是如何自定义我们自己的MessageConverter呢?有文章吗?

【讨论】:

不,这不起作用。它说没有合适的转换器。 这行得通。实际上取决于您从服务器发送的内容。就我而言,我发送的是一个字符串值。【参考方案2】:

向客户端添加一个 SimpleMessageConverter,它可以工作。

stompClient.setMessageConverter(new SimpleMessageConverter());

【讨论】:

SimpleMessageConverter 是默认值,所以这没有区别。【参考方案3】:

您似乎没有在 Web 套接字配置中配置任何 org.springframework.messaging.converter.MessageConverter。 如果你的类路径上有jackson jar,那么它将被自动拾取以进行 json 转换。对于其他转换器,您需要在 WebSocket 配置文件中进行配置。

 @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

【讨论】:

【参考方案4】:

我遇到了类似的问题(尽管我正在发送自定义对象),对我有用的只是将 Jackson2Message 消息转换器设置为

webSocketStompClient.messageConverter = new MappingJackson2MessageConverter()

我在以下网址找到了有用的信息(和示例):https://github.com/Noozen/spring-boot-websocket-client#the-java-client

【讨论】:

以上是关于如何使用和自定义 MessageConversion(Spring websocket 客户端)的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ListFragment 中使用 setEmptyView() 和自定义列表布局

如何在列表适配器中正确使用 ViewHolder 和自定义视图

Android:如何添加按钮和自定义视图

如何使用和自定义 MessageConversion(Spring websocket 客户端)

如何将 TypeScript 与 withRouter、connect、React.Component 和自定义属性一起使用?

如何使用 C# 中的 Nuget 包在谷歌分析中创建自定义维度和自定义指标