Reaktive WebSockets med fjeder 5
1. Oversigt
I denne artikel vil vi oprette et hurtigt eksempel ved hjælp af den nye Spring 5 WebSockets API sammen med reaktive funktioner leveret af Spring WebFlux.
WebSocket er en velkendt protokol, der muliggør fuld duplexkommunikation mellem klient og server, der generelt bruges i webapplikationer, hvor klienten og serveren har brug for at udveksle begivenheder med høj frekvens og med lav latenstid.
Spring Framework 5 har moderniseret WebSockets-understøttelse i rammen og tilføjer reaktive muligheder til denne kommunikationskanal.
Vi kan finde mere på Spring WebFlux her.
2. Maven-afhængigheder
Vi skal bruge afhængighed af spring-boot-starters til spring-boot-integration og spring-boot-starter-webflux, der i øjeblikket er tilgængelig på Spring Milestone Repository.
I dette eksempel bruger vi den senest tilgængelige version, 2.0.0.M7, men man skal altid få den nyeste version tilgængelig i Maven-arkivet:
org.springframework.boot spring-boot-starter-integration org.springframework.boot spring-boot-starter-webflux
3. WebSocket-konfiguration om foråret
Vores konfiguration er ret ligetil: Vi indsprøjter WebSocketHandler til at håndtere socket-sessionen i vores Spring WebSocket-applikation.
@Autowired privat WebSocketHandler webSocketHandler;
Lad os desuden oprette en HandlerMapping bønne-kommenteret metode, der er ansvarlig for kortlægningen mellem anmodninger og handlerobjekter:
@Bean public HandlerMapping webSocketHandlerMapping () {Map map = new HashMap (); map.put ("/ event-emitter", webSocketHandler); SimpleUrlHandlerMapping handlerMapping = ny SimpleUrlHandlerMapping (); handlerMapping.setOrder (1); handlerMapping.setUrlMap (kort); returhåndtering Kortlægning; }
Den URL, vi kan oprette forbindelse til, er: ws: // localhost: / event-emitter.
4. Håndtering af WebSocket-meddelelser om foråret
Vores ReactiveWebSocketHandler klasse vil være ansvarlig for styring af WebSocket-sessionen på serversiden.
Det implementerer WebSocketHandler interface, så vi kan tilsidesætte håndtere metode, som vil blive brugt til at sende meddelelsen til WebSocket-klienten:
@Component public class ReactiveWebSocketHandler implementerer WebSocketHandler {// private felter ... @ Override offentligt monohåndtag (WebSocketSession webSocketSession) {return webSocketSession.send (intervalFlux .map (webSocketSession :: textMessage)). Og (webSocketSession.receive (). (WebSocketMessage :: getPayloadAsText) .log ()); }}
5. Oprettelse af en simpel reaktiv WebSocket-klient
Lad os nu oprette en Spring Reactive WebSocket-klient, der er i stand til at oprette forbindelse og udveksle oplysninger med vores WebSocket-server.
5.1. Maven afhængighed
For det første Maven afhængigheder.
org.springframework.boot spring-boot-starter-webflux
Her bruger vi den samme spring-boot-starter-webflux, der tidligere blev brugt til at opsætte vores reaktive WebSocket-serverapplikation.
5.2. WebSocket-klient
Lad os nu oprette ReactiveClientWebSocket klasse, der er ansvarlig for at starte kommunikationen med serveren:
public class ReactiveJavaClientWebSocket {public static void main (String [] args) throw InterruptedException {WebSocketClient client = new ReactorNettyWebSocketClient (); client.execute (URI.create ("ws: // localhost: 8080 / event-emitter"), session -> session.send (Mono.just (session.textMessage ("event-spring-reactive-client-websocket")) )) .thenMany (session.receive () .map (WebSocketMessage :: getPayloadAsText) .log ()) .then ()) .block (Duration.ofSeconds (10L)); }}
I koden ovenfor kan vi se, at vi bruger ReactorNettyWebSocketClient, som er WebSocketClient implementering til brug med Reactor Netty.
Derudover opretter klienten forbindelse til WebSocket-serveren via URL'en ws: // localhost: 8080 / event-emitter, oprettelse af en session, så snart den er forbundet til serveren.
Vi kan også se, at vi sender en besked til serveren (“event-spring-reactive-client-websocket“) Sammen med anmodningen om forbindelse.
Desuden er metoden sende påberåbes og forventer som parameter en variabel af typen Forlægger, som i vores tilfælde vores Forlægger er Mono og T er en simpel streng “event-me-from-reactive-java-client-websocket“.
Desuden er derefterMange (…) metode forventer en Strøm af typen Snor påberåbes. Det modtage() metode får strømmen af indgående beskeder, som senere konverteres til strenge.
Endelig blev blok() metode tvinger klienten til at afbryde forbindelsen til serveren efter den givne tid (10 sekunder i vores eksempel).
5.3. Start af klienten
For at køre det skal du sørge for, at Reactive WebSocket Server er i gang. Start derefter ReactiveJavaClientWebSocket klasse, og vi kan se på sysout log de begivenheder, der udsendes:
[reaktor-http-nio-4] INFO reaktor.Flux.Map.1 - onNext ({"eventId": "6042b94f-fd02-47a1-911d-dacf97f12ba6", "eventDt": "2018-01-11T23: 29: 26.900 "})
Vi kan også se loggen fra vores Reactive WebSocket-server meddelelsen sendt af klienten under forbindelsesforsøget:
[reactor-http-nio-2] reactor.Flux.Map.1: onNext (event-me-from-reactive-java-client)
Vi kan også se meddelelsen om afbrudt forbindelse, når klienten har afsluttet sine anmodninger (i vores tilfælde efter de 10 sekunder):
[reaktor-http-nio-2] reaktor.Flux.Map.1: onComplete ()
6. Oprettelse af en browser WebSocket-klient
Lad os oprette en simpel HTML / Javascript-klient WebSocket til at forbruge vores reaktive WebSocket-serverapplikation.
var clientWebSocket = ny WebSocket ("ws: // localhost: 8080 / event-emitter"); clientWebSocket.onopen = funktion () {console.log ("clientWebSocket.onopen", clientWebSocket); console.log ("clientWebSocket.readyState", "websocketstatus"); clientWebSocket.send ("begivenhed-mig-fra-browser"); } clientWebSocket.onclose = funktion (fejl) {console.log ("clientWebSocket.onclose", clientWebSocket, fejl); begivenheder ("Lukning af forbindelse"); } clientWebSocket.onerror = funktion (fejl) {console.log ("clientWebSocket.onerror", clientWebSocket, fejl); begivenheder ("Der opstod en fejl"); } clientWebSocket.onmessage = funktion (fejl) {console.log ("clientWebSocket.onmessage", clientWebSocket, fejl); begivenheder (error.data); } funktionshændelser (responsEvent) {document.querySelector (". events"). innerHTML + = responsEvent + ""; }
Når WebSocket-serveren kører, åbner denne HTML-fil i en browser (f.eks. Chrome, Internet Explorer, Mozilla Firefox osv.), Skal vi se begivenhederne udskrives på skærmen med en forsinkelse på 1 sekund pr. Begivenhed som defineret i vores 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. Konklusion
Her har vi præsenteret et eksempel på, hvordan man opretter en WebSocket-kommunikation mellem server og klient ved hjælp af Spring 5 Framework, implementering af de nye reaktive funktioner leveret af Spring Webflux.
Som altid kan det fulde eksempel findes i vores GitHub-lager.