使用Spring 4从Java客户端连接实现的WebSockets上的Stomp

19
我收到了一个基于Spring使用STOMP over WebSockets Messaging实现的Web应用程序,类似于这里所描述的(后端使用RabbitMQ)。它运行在Tomcat上,我可以使用常规URL(例如http://host/server/)连接到应用程序。我还收到了一个演示客户端 - 一个JSPX页面,它使用Modernizr WebSockets和SockJS。演示客户端中的连接代码如下:
if (Modernizr.websockets) {
    socket = new WebSocket('ws://host/server/endpointx');
}
else {
    socket = new SockJS('/server/endpointy');
}

stompClient = Stomp.over(socket);
stompClient.connect(headers, function(frame) { ... });
....

演示客户端运行正常(当我在浏览器中加载JSPX页面时,我可以连接到服务器)。但我的目标是使用一些Java STOMP库连接到同一台服务器。问题是,我尝试的库需要主机端口作为连接参数:例如,使用ActiveMQ Stomp library

StompConnection connection = new StompConnection();
connection.open("host", port);
connection.connect(new HashMap<String, String>());

如果我将port指定为61613,连接会成功,但是我会直接连接到RabbitMQ而不是我的服务器(这不是我想要的)。如果我指定8080(或80),连接时会出现错误。

java.io.EOFException at java.io.DataInputStream.readByte(Unknown Source) at org.apache.activemq.transport.stomp.StompWireFormat.unmarshal(StompWireFormat.java:137) at org.apache.activemq.transport.stomp.StompConnection.receive(StompConnection.java:77) at org.apache.activemq.transport.stomp.StompConnection.receive(StompConnection.java:68) at org.apache.activemq.transport.stomp.StompConnection.connect(StompConnection.java:139) at ....stomp.impl.activemq.ActiveMQStompDriver.connect(ActiveMQStompDriver.java:39) ... 25 more

跟踪显示,这是因为CONNECT帧从未收到期望的CONNECTED帧(实际上,它没有收到任何回复)。

所以我感到困惑:我是否使用了错误的端口?或者遇到了一些库不兼容的问题?或者我需要以某种方式告诉Tomcat,我想要将HTTP连接升级为WebSockets

如果上述问题难以回答,那么这个问题同样有用:如何使用Java连接到在Tomcat上运行的STOMP over WebSockets消息通道的Spring应用程序?

1个回答

1
我发现时应该发布答案。 为了实现连接到Tomcat而不是直接连接到RabbitMQ的Java客户端,Java客户端不仅应该实现STOMP Over WebSockets,还应该进行握手

握手旨在与基于HTTP的服务器端软件和中介兼容,以便单个端口可由HTTP客户端与该服务器交谈以及WebSocket客户端与该服务器交谈。为此,WebSocket客户端的握手是一个HTTP升级请求

我尝试使用的库简单地缺少这种功能。它们试图直接执行WebSocket连接而没有握手。
因此,回答我的问题:
  • 库必须支持开放式握手
  • 对于主机和端口,您需要指定Tomcat的主机(如果与RabbitMQ不同)和Web端口(例如8080),而不是RabbitMQ端口
我最终使用了Spring WebSocket库,它可以轻松实现所有这些。下面是最简单的设置:
taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.setPoolSize(N); // N = number of threads
taskScheduler.afterPropertiesSet();

stompClient = new WebSocketStompClient(new StandardWebSocketClient());
stompClient.setTaskScheduler(taskScheduler);
stompClient.setMessageConverter(new MappingJackson2MessageConverter()); 

WebSocketHttpHeaders handshakeHeaders = new WebSocketHttpHeaders(); // you can add additional headers here for Tomcat

// Here's the main piece other libraries were missing:
// The following request will perform both, handshake and connection
// hence it gets both sets of headers (for Tomcat and for Stomp)
ListenableFuture<StompSession> future = stompClient.connect(
            url,
            handshakeHeaders,
            new StompHeaders(),
            new CustomStompSessionHandlerAdapter(this)); // called from class that also was implementing CustomStompSessionHandlerAdapter, but this could be separate class as well.

同时请参阅Spring参考文档中的WebSocket支持部分


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接