Перейти к основному содержимому

Java-клиент для WebSockets API

· 4 мин. чтения

1. Введение

HTTP (протокол передачи гипертекста) — это протокол запроса-ответа без сохранения состояния. Его простой дизайн делает его очень масштабируемым, но неподходящим и неэффективным для высокоинтерактивных веб-приложений в реальном времени из-за объема служебных данных, которые необходимо передавать вместе с каждым запросом/ответом.

Поскольку HTTP является синхронным, а приложения реального времени должны быть асинхронными, любые решения, такие как опрос или длительный опрос ( Comet ), как правило, сложны и неэффективны.

Чтобы решить указанную выше проблему, нам нужен основанный на стандартах, двунаправленный и полнодуплексный протокол, который мог бы использоваться как серверами, так и клиентами, и это привело к введению API JSR 356 — в этой статье мы покажу пример его использования.

2. Настройка

Давайте включим зависимости 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>

Мы всегда можем получить последние версии зависимостей от Maven Central для spring-websocket и spring-messaging .

3. ТОМП

Stream Text-Oriented Messaging Protocol (STOMP) — это простой, совместимый проводной формат, который позволяет клиенту и серверам обмениваться данными практически со всеми брокерами сообщений. Это альтернатива AMQP (протокол расширенной очереди сообщений) и JMS (служба обмена сообщениями Java).

STOMP определяет протокол для взаимодействия клиент/сервер с использованием семантики обмена сообщениями. Семантика находится поверх WebSockets и определяет фреймы, которые сопоставляются с фреймами WebSockets.

Использование STOMP дает нам гибкость для разработки клиентов и серверов на разных языках программирования. В этом текущем примере мы будем использовать STOMP для обмена сообщениями между клиентом и сервером.

4. Веб-сокет-сервер

Подробнее о построении серверов WebSocket можно прочитать в этой статье .

5. Веб-сокет-клиент

Для связи с сервером WebSocket клиент должен инициировать соединение WebSocket, отправив HTTP-запрос на сервер с правильно установленным заголовком Upgrade :

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

Обратите внимание, что URL-адреса веб-сокетов используют схемы ws и wss , вторая означает безопасные веб-сокеты.

Сервер отвечает, отправляя в ответ заголовок Upgrade , если включена поддержка WebSockets.

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

Как только этот процесс (также известный как рукопожатие WebSocket) завершен, первоначальное соединение HTTP заменяется соединением WebSocket поверх того же соединения TCP/IP, после чего обе стороны могут обмениваться данными.

Это подключение на стороне клиента инициируется экземпляром WebSocketStompClient .

5.1. WebSocketStompClient _ ``

Как описано в разделе 3, сначала нам нужно установить соединение WebSocket, и это делается с помощью класса WebSocketClient .

WebSocketClient можно настроить с помощью :

  • StandardWebSocketClient предоставляется любой реализацией JSR-356, такой как Tyrus.
  • JettyWebSocketClient предоставляется собственным API WebSocket Jetty 9+.
  • Любая реализация Spring WebSocketClient

Мы будем использовать 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.

По умолчанию WebSocketStompClient поддерживает SimpleMessageConverter . Поскольку мы имеем дело с сообщениями JSON, мы устанавливаем конвертер сообщений на MappingJackson2MessageConverter , чтобы преобразовать полезную нагрузку JSON в объект.

При подключении к конечной точке мы передаем экземпляр StompSessionHandler , который обрабатывает такие события, как afterConnected и handleFrame .

Если наш сервер поддерживает SockJs, мы можем модифицировать клиент для использования SockJsClient вместо StandardWebSocketClient.

5.2. StompSessionHandler _ ``

Мы можем использовать StompSession для подписки на тему WebSocket. Это можно сделать, создав экземпляр StompSessionHandlerAdapter , который, в свою очередь, реализует StompSessionHandler .

StompSessionHandler предоставляет события жизненного цикла для сеанса STOMP. События включают обратный вызов при установлении сеанса и уведомления в случае сбоев.

Как только клиент 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());
}

Убедитесь, что сервер 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. Заключение

В этом кратком руководстве мы реализовали клиент WebSocket на основе Spring.

Полную реализацию можно найти на GitHub .