Reactive WebSockets met veer 5

1. Overzicht

In dit artikel gaan we een snel voorbeeld maken met behulp van de nieuwe Spring 5 WebSockets API, samen met reactieve functies van Spring WebFlux.

WebSocket is een bekend protocol dat full-duplex communicatie tussen client en server mogelijk maakt, meestal gebruikt in webapplicaties waarbij de client en server gebeurtenissen met hoge frequentie en met lage latentie moeten uitwisselen.

Spring Framework 5 heeft WebSockets-ondersteuning in het framework gemoderniseerd, waardoor reactieve mogelijkheden aan dit communicatiekanaal zijn toegevoegd.

We kunnen hier meer vinden over Spring WebFlux.

2. Maven afhankelijkheden

We gaan de afhankelijkheden van spring-boot-starters gebruiken voor spring-boot-integratie en spring-boot-starter-webflux, momenteel beschikbaar in Spring Milestone Repository.

In dit voorbeeld gebruiken we de nieuwste beschikbare versie, 2.0.0.M7, maar je moet altijd de nieuwste versie beschikbaar hebben in de Maven-repository:

 org.springframework.boot spring-boot-starter-integratie org.springframework.boot spring-boot-starter-webflux 

3. WebSocket-configuratie in het voorjaar

Onze configuratie is vrij eenvoudig: we injecteren het WebSocketHandler om de socketsessie af te handelen in onze Spring WebSocket-applicatie.

@Autowired privé WebSocketHandler webSocketHandler; 

Laten we bovendien een HandlerMapping bean-geannoteerde methode die verantwoordelijk is voor de toewijzing tussen verzoeken en handlerobjecten:

@Bean openbare HandlerMapping webSocketHandlerMapping () {Map map = new HashMap (); map.put ("/ event-emitter", webSocketHandler); SimpleUrlHandlerMapping handlerMapping = nieuwe SimpleUrlHandlerMapping (); handlerMapping.setOrder (1); handlerMapping.setUrlMap (kaart); terug handlerMapping; }

De URL waarmee we verbinding kunnen maken, is: ws: // localhost: / event-emitter.

4. WebSocket-berichtafhandeling in het voorjaar

Onze ReactiveWebSocketHandler class zal verantwoordelijk zijn voor het beheren van de WebSocket-sessie op de server.

Het implementeert het WebSocketHandler interface zodat we de handvat methode, die zal worden gebruikt om het bericht naar de WebSocket-client te sturen:

@Component openbare klasse ReactiveWebSocketHandler implementeert WebSocketHandler {// privévelden ... @Override openbare mono-handle (WebSocketSession webSocketSession) {retourneer webSocketSession.send (intervalFlux .map (webSocketSession :: textMessage)). En (webSocketSession.mapreceive (). (WebSocketMessage :: getPayloadAsText) .log ()); }}

5. Een eenvoudige reactieve WebSocket-client maken

Laten we nu een Spring Reactive WebSocket-client maken die verbinding kan maken en informatie kan uitwisselen met onze WebSocket-server.

5.1. Afhankelijkheid van Maven

Ten eerste, de Maven-afhankelijkheden.

 org.springframework.boot spring-boot-starter-webflux 

Hier gebruiken we dezelfde spring-boot-starter-webflux die eerder werd gebruikt om onze reactieve WebSocket-servertoepassing op te zetten.

5.2. WebSocket-client

Laten we nu het ReactiveClientWebSocket class, verantwoordelijk voor het starten van de communicatie met de server:

openbare klasse ReactiveJavaClientWebSocket {openbare statische leegte hoofd (String [] args) gooit InterruptedException {WebSocketClient-client = nieuwe ReactorNettyWebSocketClient (); client.execute (URI.create ("ws: // localhost: 8080 / event-emitter"), sessie -> session.send (Mono.just (session.textMessage ("event-spring-reactive-client-websocket") )) .thenMany (session.receive () .map (WebSocketMessage :: getPayloadAsText) .log ()) .then ()) .block (Duration.ofSeconds (10L)); }}

In de bovenstaande code kunnen we zien dat we de ReactorNettyWebSocketClient, welke is de WebSocketClient implementatie voor gebruik met Reactor Netty.

Bovendien maakt de client via de URL verbinding met de WebSocket-server ws: // localhost: 8080 / event-emitter, het opzetten van een sessie zodra deze is verbonden met de server.

We kunnen ook zien dat we een bericht naar de server sturen ("event-spring-reactive-client-websocket“) Samen met het verbindingsverzoek.

Bovendien is de methode sturen wordt aangeroepen, in afwachting van een parameter van een type variabele Uitgever, die in ons geval onze Uitgever is Mono en T is een simpele String “event-me-van-reactieve-java-client-websocket“.

Bovendien is de danVeel (...) methode verwacht een Flux van het type Draad wordt aangeroepen. De te ontvangen() methode haalt de stroom van inkomende berichten op, die later worden omgezet in strings.

eindelijk, de blok() methode dwingt de client om de verbinding met de server te verbreken na de opgegeven tijd (10 seconden in ons voorbeeld).

5.3. De client starten

Om het uit te voeren, moet u ervoor zorgen dat de Reactive WebSocket Server actief is. Start vervolgens het ReactiveJavaClientWebSocket klasse, en we kunnen zien op de sysout log de gebeurtenissen die worden verzonden:

[reactor-http-nio-4] INFO reactor.Flux.Map.1 - onNext ({"eventId": "6042b94f-fd02-47a1-911d-dacf97f12ba6", "eventDt": "2018-01-11T23: 29: 26.900 "})

We kunnen ook in het logboek van onze Reactive WebSocket-server het bericht zien dat door de client is verzonden tijdens de verbindingspoging:

[reactor-http-nio-2] reactor.Flux.Map.1: onNext (event-me-from-reactive-java-client)

We kunnen ook het bericht zien dat de verbinding is verbroken nadat de client zijn verzoeken heeft voltooid (in ons geval na de 10 seconden):

[reactor-http-nio-2] reactor.Flux.Map.1: onComplete ()

6. Een browser WebSocket-client maken

Laten we een eenvoudige HTML / Javascript-client WebSocket maken om onze reactieve WebSocket-servertoepassing te gebruiken.

 var clientWebSocket = nieuwe WebSocket ("ws: // localhost: 8080 / event-emitter"); clientWebSocket.onopen = function () {console.log ("clientWebSocket.onopen", clientWebSocket); console.log ("clientWebSocket.readyState", "websocketstatus"); clientWebSocket.send ("event-me-from-browser"); } clientWebSocket.onclose = functie (fout) {console.log ("clientWebSocket.onclose", clientWebSocket, fout); evenementen ("Verbinding verbreken"); } clientWebSocket.onerror = functie (fout) {console.log ("clientWebSocket.onerror", clientWebSocket, fout); events ("Er is een fout opgetreden"); } clientWebSocket.onmessage = functie (fout) {console.log ("clientWebSocket.onmessage", clientWebSocket, fout); gebeurtenissen (error.data); } functiegebeurtenissen (responseEvent) {document.querySelector (". events"). innerHTML + = responseEvent + "

"; }

Terwijl de WebSocket-server actief is en dit HTML-bestand opent in een browser (bijvoorbeeld: Chrome, Internet Explorer, Mozilla Firefox enz.), Zouden we de gebeurtenissen op het scherm moeten zien worden afgedrukt, met een vertraging van 1 seconde per gebeurtenis, zoals gedefinieerd in onze WebSocket-server.

{"eventId": "c25975de-6775-4b0b-b974-b396847878e6", "eventDt": "2018-01-11T23: 56: 09.780"} {"eventId": "ac74170b-1f71-49d3-8737-b3f9a8a352f9", "eventDt": "2018-01-11T23: 56: 09.781"} {"eventId": "40d8f305-f252-4c14-86d7-ed134d3e10c6", "eventDt": "2018-01-11T23: 56: 09.782"}

7. Conclusie

Hier hebben we een voorbeeld gepresenteerd van hoe u een WebSocket-communicatie tussen server en client kunt creëren met behulp van Spring 5 Framework, waarbij de nieuwe reactieve functies van Spring Webflux worden geïmplementeerd.

Zoals altijd is het volledige voorbeeld te vinden in onze GitHub-repository.