通过Java客户端使用Spring 4实现的WebSockets连接到Stomp

时间:2016-08-08 00:37:37

标签: tomcat websocket stomp spring-websocket java-websocket

我收到了一个Web应用程序,使用Spring通过WebSockets Messaging使用STOMP实现,类似于所描述的here(在后端使用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)       在org.apache.activemq.transport.stomp.StompWireFormat.unmarshal(StompWireFormat.java:137)       在org.apache.activemq.transport.stomp.StompConnection.receive(StompConnection.java:77)       在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个

和跟踪显示这是因为CONNECT框架从未收到预期的CONNECTED框架(事实上,它没有收到任何回复)。

所以我很困惑:我使用了错误的端口吗?或处理一些库不兼容?或者我是否需要以某种方式向Tomcat表明我想要upgrade HTTP connection to WebSockets

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

2 个答案:

答案 0 :(得分:0)

  

我收到了一个Web应用程序,使用Spring通过WebSockets Messaging使用STOMP实现,类似于此处描述的(在后端使用RabbitMQ)。它在Tomcat上运行,我可以使用常规URL(例如http://host/server/)连接到应用程序。

这仅供答案后面的参考:

Browser -> WebSocket -> Spring STOMP Broker Relay -> RabbitMQ

工作示例在最终用户的浏览器中创建一个Javscript客户端。它通过WebSockets连接到您的Tomcat服务器&amp;您的应用中的Spring STOMP Broker Relay。顾名思义,继电器将通过WebSocket接收的STOMP消息中继到连接到RabbitMQ的实际套接字(也通过STOMP)。

  

我还获得了一个演示客户端 - 一个JSPX页面,它使用了Modernizr WebSockets和SockJS。

与答案无关,但您无需检查客户端浏览器是否支持WebSockets。 SockJS将为您执行此操作并自动选择要使用的最佳通道。在任何不在限制性代理之后的现代浏览器中,这将是WebSockets。

  

但我的目标是使用一些Java STOMP库连接到同一台服务器。问题是,我尝试过的库需要主机和端口作为连接参数

我怀疑Java STOMP客户端将被设计为在这种情况下工作(尽管一切皆有可能)。 通常,Java STOMP客户端将运行服务器端或者它将直接连接到STOMP服务器的某个地方,在这种情况下意味着直接连接到RabbitMQ。

你提到能够直接连接到Rabbit,所以这是一个可能的解决方案(你说你不想这样做,但不是为什么,请随意在评论中澄清这一点)。如果您的代码在服务器端运行,那么这绝对是可行的方法。通过WebSocket通道和Spring代理中继只会增加额外的跳跃和不必要的延迟。

另一个解决方案是使用能够通过WebSockets和&amp; S进行通信的Java客户端。 STOMP。如果你的Java代码在某个地方作为远程客户端运行而且它无法直接与RabbitMQ对话,我只会推荐这个。

  

所以我很困惑:我使用了错误的端口吗?或处理一些库不兼容?或者我是否需要以某种方式指示Tomcat我想要将HTTP连接升级到WebSockets?

61613是直接与RabbitMQ通信的正确端口,如果这是你想要做的。建立WebSocket连接的端口只是Tomcat监听连接的标准HTTP或HTTPS端口(默认为8080/8443)。您不能直接向Tomcat说STOMP,它不了解该协议。您必须启动WebSocket连接,然后将STOMP说成您的应用程序(即Spring STOMP代理中继)。

要做到这一点,您需要一个知道如何说WebSocket&amp;可以通过WebSocket通道说STOMP的客户端。您当前的客户端正在尝试与Tomcat建立常规套接字连接,而不是WebSocket连接。要成功,首先需要启动WebSocket连接,然后通过WebSocket连接发送STOMP消息。

当您的演示在浏览器中运行时,WebSocket连接由您的浏览器和SockJS处理,您的Javascript STOMP客户端通过STOMP与应用程序的WebSocket连接进行通信(参见上面的ASCII图)。

  

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

我认为你通常不想这样做。如果您在Tomcat上运行Java代码,那么使用Java STOMP客户端直接连接RabbitMQ(即您的STOMP服务器)会更有效。

STOMP over WebSockets主要是为了使远程运行的基于浏览器的客户端能够轻松安全地连接和发送消息,而无需直接访问您的RabbitMQ服务器。

希望有所帮助!

答案 1 :(得分:0)

我应该找到答案了。 为了实现Java客户端,连接到Tomcat而不直接连接到RabbitMQ,Java客户端不仅应实现STOMP Over WebSockets,还应实现an opening handshake

  

开放式握手旨在与基于HTTP的兼容      服务器端软件和中介,因此可以将单个端口      与该服务器和WebSocket进行通信的HTTP客户端都使用      客户与该服务器通信。为此,WebSocket客户端的      握手是HTTP升级请求

我尝试使用的库只是缺少此功能。他们尝试不握手而直接执行WebSocket连接。

所以回答我自己的问题:

  • 图书馆必须支持开放握手
  • 对于主机和端口,您需要指定Tomcat的主机(与RabbitMQ不同)和 Web端口(例如8080),而不是RabbitMQ端口

我最终使用了Spring WebSocket library,这使所有操作变得非常容易。这是最简单的设置:

home
  oddsportal
    oddsportalenv
      bin
      ...
    oddsportal
      app
        ...
      oddsportal
        settings
        wsgi
        ...
      manage.py
      ...

另请参见WebSocket Support section in Spring reference