A Java Client for a WebSockets API – 一个WebSockets API的Java客户端

最后修改: 2017年 6月 26日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.介绍

HTTP (Hypertext Transfer Protocol) is a stateless request-response protocol. Its simple design makes it very scalable but unsuitable and inefficient for highly interactive real-time web applications because of the amount of overhead that needs to be transmitted along with every request/response.

HTTP(超文本传输协议)是一个无状态的请求-响应协议。它的简单设计使其具有很强的可扩展性,但对于高度互动的实时网络应用来说是不合适的,也是低效的,因为每次请求/响应都需要传输大量的开销。

Since HTTP is synchronous and real-time applications need to be asynchronous, any solutions like polling or long polling (Comet) tend to be complicated and inefficient.

由于HTTP是同步的,而实时应用程序需要是异步的,任何像轮询或长轮询(Comet)这样的解决方案往往是复杂而低效的。

To solve the above-specified problem, we need a standards-based, bi-directional and full-duplex protocol which could be used by both servers and clients, and this led to the introduction of JSR 356 API – in this article, we’ll show an example usage of it.

为了解决上述问题,我们需要一个基于标准的、双向的和全双工的协议,它可以被服务器和客户使用,这导致了JSR 356 API的引入 – 在这篇文章中,我们将展示它的一个使用示例。

2. Setup

2.设置

Let’s include the Spring WebSocket dependencies to our project:

让我们把Spring WebSocket的依赖关系纳入我们的项目。

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-websocket</artifactId>
    <version>5.2.2.RELEASE</version>
 </dependency>
 <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-messaging</artifactId>
    <version>5.2.2.RELEASE</version>
 </dependency>

We can always get the latest versions of the dependencies from Maven Central for spring-websocket and spring-messaging.

我们可以随时从Maven中心获取spring-websocketspring-messaging的最新依赖版本。

3. STOMP

3.STOMP

Stream Text-Oriented Messaging Protocol (STOMP) is a simple, interoperable wire format that allows client and servers to communicate with almost all the message brokers. It is an alternative to AMQP (Advanced Message Queuing Protocol) and JMS (Java Messaging Service).

面向流文本的消息传输协议(STOMP)是一种简单的、可互操作的线格式,允许客户端和服务器与几乎所有的消息中介进行通信。它是AMQP(高级消息队列协议)和JMS(Java消息传递服务)的替代品。

STOMP defines a protocol for client/server to communicate using messaging semantics. The semantics are on top of the WebSockets and defines frames that are mapped onto WebSockets frames.

STOMP定义了一个客户端/服务器使用信息传递语义进行通信的协议。该语义是在WebSockets之上,并定义了映射到WebSockets框架上的框架。

Using STOMP gives us the flexibility to develop clients and servers in different programming languages. In this current example, we will use STOMP for messaging between client and server.

使用STOMP使我们可以灵活地用不同的编程语言来开发客户端和服务器。在目前的这个例子中,我们将使用STOMP在客户端和服务器之间进行信息传递。

4. WebSocket Server

4.WebSocket服务器

You can read more about building WebSocket servers in this article.

您可以在这篇文章中阅读有关构建WebSocket服务器的更多信息。

5. WebSocket Client

5.WebSocket客户端

To communicate with the WebSocket server, the client has to initiate the WebSocket connection by sending an HTTP request to a server with an Upgrade header set properly:

为了与WebSocket服务器通信,客户端必须通过向服务器发送HTTP请求来启动WebSocket连接,并正确设置Upgrade头。

GET ws://websocket.example.com/ HTTP/1.1
Origin: http://example.com
Connection: Upgrade
Host: websocket.example.com
Upgrade: websocket

Please note that the WebSocket URLs use ws and wss schemes, the second one signifies secure WebSockets.

请注意,WebSocket URLs使用wswss方案,第二个方案标志着安全WebSockets。

The server responds back by sending the Upgrade header in the response if WebSockets support is enabled.

如果启用了WebSockets支持,服务器通过在响应中发送Upgrade头来进行响应。

HTTP/1.1 101 WebSocket Protocol Handshake
Date: Wed, 16 Oct 2013 10:07:34 GMT
Connection: Upgrade
Upgrade: WebSocket

Once this process (also known as WebSocket handshake) is completed, the initial HTTP connection is replaced by WebSocket connection on top of same TCP/IP connection after which either parties can share data.

一旦这个过程(也称为WebSocket握手)完成,最初的HTTP连接就被同一TCP/IP连接之上的WebSocket连接所取代,之后任何一方都可以分享数据。

This client-side connection is initiated by WebSocketStompClient instance.

这个客户端连接是由WebSocketStompClient实例发起的。

5.1. The WebSocketStompClient

5.1.WebSocketStompClient

As described in section 3, we first need to establish a WebSocket connection, and this is done using WebSocketClient class.

如第3节所述,我们首先需要建立一个WebSocket连接,这需要使用WebSocketClient类来完成。

The WebSocketClient can be configured using:

WebSocketClient可以通过以下方式进行配置。

  • StandardWebSocketClient provided by any JSR-356 implementation like Tyrus
  • JettyWebSocketClient provided by Jetty 9+ native WebSocket API
  • Any implementation of Spring’s WebSocketClient

We will use StandardWebSocketClient, an implementation of WebSocketClient in our example:

我们将使用StandardWebSocketClient,这是WebSocketClient的一个实现。

WebSocketClient client = new StandardWebSocketClient();

WebSocketStompClient stompClient = new WebSocketStompClient(client);
stompClient.setMessageConverter(new MappingJackson2MessageConverter());

StompSessionHandler sessionHandler = new MyStompSessionHandler();
stompClient.connect(URL, sessionHandler);

new Scanner(System.in).nextLine(); // Don't close immediately.

By default, WebSocketStompClient supports SimpleMessageConverter. Since we are dealing with JSON messages, we set the message converter to MappingJackson2MessageConverter so as to convert the JSON payload to object.

默认情况下,WebSocketStompClient支持SimpleMessageConverter。由于我们处理的是JSON消息,我们将消息转换器设置为MappingJackson2MessageConverter,以便将JSON有效载荷转换为对象。

While connecting to an endpoint, we pass an instance of StompSessionHandler, which handles the events like afterConnected and handleFrame.

在连接到一个端点时,我们传递一个StompSessionHandler的实例,它处理afterConnectedhandleFrame等事件。

If our server has SockJs support, then we can modify the client to use SockJsClient instead of StandardWebSocketClient.

如果我们的服务器支持SockJs,那么我们可以修改客户端以使用SockJsClient而不是StandardWebSocketClient.

5.2. The StompSessionHandler

5.2.StompSessionHandler

We can use a StompSession to subscribe to a WebSocket topic. This can be done by creating an instance of StompSessionHandlerAdapter which in turn implements the StompSessionHandler.

我们可以使用StompSession来订阅一个WebSocket主题。这可以通过创建一个StompSessionHandlerAdapter的实例来实现,该实例又实现了StompSessionHandler

A StompSessionHandler provides lifecycle events for a STOMP session. The events include a callback when the session is established and notifications in case of failures.

一个StompSessionHandler为STOMP会话提供生命周期事件。这些事件包括会话建立时的回调以及失败时的通知。

As soon as the WebSocket client connects to the endpoint, the StompSessionHandler is notified and the afterConnected() method is called where we use the StompSession to subscribe to the topic:

一旦WebSocket客户端连接到端点,StompSessionHandler就会被通知,afterConnected()方法被调用,在这里我们使用StompSession来订阅该主题。

@Override
public void afterConnected(
  StompSession session, StompHeaders connectedHeaders) {
    session.subscribe("/topic/messages", this);
    session.send("/app/chat", getSampleMessage());
}
@Override
public void handleFrame(StompHeaders headers, Object payload) {
    Message msg = (Message) payload;
    logger.info("Received : " + msg.getText()+ " from : " + msg.getFrom());
}

Make sure that the WebSocket server is running and running the client, the message will be displayed on the console:

确保WebSocket服务器正在运行并运行客户端,信息将显示在控制台。

INFO o.b.w.client.MyStompSessionHandler - New session established : 53b993eb-7ad6-4470-dd80-c4cfdab7f2ba
INFO o.b.w.client.MyStompSessionHandler - Subscribed to /topic/messages
INFO o.b.w.client.MyStompSessionHandler - Message sent to websocket server
INFO o.b.w.client.MyStompSessionHandler - Received : Howdy!! from : Nicky

6. Conclusion

6.结论

In this quick tutorial, we have implemented a Spring-based WebSocket client.

在这个快速教程中,我们实现了一个基于Spring的WebSocket客户端。

The complete implementation could be found over on GitHub.

完整的实现可以在GitHub上找到over