Ein Java-Client für eine WebSockets-API

Ein Java-Client für eine WebSockets-API

1. Einführung

HTTP (Hypertext Transfer Protocol) ist ein zustandsloses Request-Response-Protokoll. Das einfache Design macht es sehr skalierbar, aber für hochinteraktive Echtzeit-Webanwendungen ungeeignet und ineffizient, da mit jeder Anfrage / Antwort ein hoher Overhead übertragen werden muss.

Da HTTP synchron ist und Echtzeitanwendungen asynchron sein müssen, sind Lösungen wie Polling oder Long Polling (Comet) in der Regel kompliziert und ineffizient.

Um das oben angegebene Problem zu lösen, benötigen wir ein standardbasiertes, bidirektionales und Vollduplex-Protokoll, das sowohl von Servern als auch von Clients verwendet werden kann. Dies führte zur Einführung vonJSR 356 API - in diesem Artikel Wir zeigen ein Beispiel für die Verwendung.

2. Konfiguration

Nehmen wir die Spring WebSocket-Abhängigkeiten in unser Projekt auf:


    org.springframework
    spring-websocket
    5.0.5.RELEASE
 
 
    org.springframework
    spring-messaging
    5.0.5.RELEASE
 

Wir können immer die neuesten Versionen der Abhängigkeiten von Maven Central fürspring-websocket undspring-messaging erhalten.

3. STAMPFEN

Stream Text-Oriented Messaging Protocol (STOMP) ist ein einfaches, interoperables Verbindungsformat, mit dem Client und Server mit fast allen Nachrichtenbrokern kommunizieren können. Es ist eine Alternative zu AMQP (Advanced Message Queuing Protocol) und JMS (Java Messaging Service).

STOMP definiert ein Protokoll für die Kommunikation zwischen Client und Server mithilfe der Nachrichtensemantik. Die Semantik befindet sich über den WebSockets und definiert Frames, die auf WebSockets-Frames abgebildet werden.

Mit STOMP können wir Clients und Server in verschiedenen Programmiersprachen entwickeln. In diesem aktuellen Beispiel verwenden wir STOMP für den Nachrichtenaustausch zwischen Client und Server.

4. WebSocket Server

Weitere Informationen zum Erstellen von WebSocket-Servern finden Sie inarticle.

5. WebSocket Client

Um mit dem WebSocket-Server zu kommunizieren, muss der Client die WebSocket-Verbindung initiieren, indem er eine HTTP-Anforderung an einen Server sendet, dessen HeaderUpgradeordnungsgemäß festgelegt ist:

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

Bitte beachten Sie, dass die WebSocket-URLs die Schemataws undwssverwenden, die zweite bezeichnet sichere WebSockets.

Der Server antwortet, indem er den HeaderUpgradein der Antwort sendet, wenn die WebSockets-Unterstützung aktiviert ist.

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

Sobald dieser Vorgang (auch als WebSocket-Handshake bezeichnet) abgeschlossen ist, wird die ursprüngliche HTTP-Verbindung durch eine WebSocket-Verbindung über derselben TCP / IP-Verbindung ersetzt, über die beide Parteien Daten gemeinsam nutzen können.

Diese clientseitige Verbindung wird von der Instanz vonWebSocketStompClientinitiiert.

5.1. DieWebSocketStompClient

Wie in Abschnitt 3 beschrieben, müssen wir zuerst eine WebSocket-Verbindung herstellen, und dies erfolgt mit der KlasseWebSocketClient.

DieWebSocketClient können konfiguriert werden mit:

  • StandardWebSocketClient, die von einer JSR-356-Implementierung wie Tyrus bereitgestellt werden

  • JettyWebSocketClient werden von der nativen WebSocket-API von Jetty 9+ bereitgestellt

  • Jede Implementierung von Spring'sWebSocketClient

Wir werdenStandardWebSocketClient verwenden, eine Implementierung vonWebSocketClient in unserem Beispiel:

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.

Standardmäßig unterstütztWebSocketStompClientSimpleMessageConverter. Da es sich um JSON-Nachrichten handelt, setzen wir den Nachrichtenkonverter aufMappingJackson2MessageConverter, um die JSON-Nutzdaten in Objekte zu konvertieren.

Während der Verbindung zu einem Endpunkt übergeben wir eine Instanz vonStompSessionHandler, die Ereignisse wieafterConnected undhandleFrame behandelt.

Wenn unser Server SockJs unterstützt, können wir den Client so ändern, dassSockJsClient anstelle vonStandardWebSocketClient. verwendet wird

5.2. DieStompSessionHandler

Wir könnenStompSession verwenden, um ein WebSocket-Thema zu abonnieren. Dies kann durch Erstellen einer Instanz vonStompSessionHandlerAdapter erfolgen, die wiederum dieStompSessionHandler implementiert.

AStompSessionHandler liefert Lebenszyklusereignisse für eine STOMP-Sitzung. Zu den Ereignissen gehören ein Rückruf beim Aufbau der Sitzung und Benachrichtigungen bei Fehlern.

Sobald der WebSocket-Client eine Verbindung zum Endpunkt herstellt, werden dieStompSessionHandler benachrichtigt und dieafterConnected()-Methode aufgerufen, wobei wir dieStompSession verwenden, um das Thema zu abonnieren:

@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());
}

Stellen Sie sicher, dass der WebSocket-Server ausgeführt wird und der Client ausgeführt wird. Die Meldung wird in der Konsole angezeigt:

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. Fazit

In diesem kurzen Tutorial haben wir einen Spring-basierten WebSocket-Client implementiert.

Die vollständige Implementierung konnteover on GitHub gefunden werden.