WebSockets Reaktif dengan Spring 5

1. Ikhtisar

Pada artikel ini, kami akan membuat contoh cepat menggunakan Spring 5 WebSockets API bersama dengan fitur reaktif yang disediakan oleh Spring WebFlux.

WebSocket adalah protokol terkenal yang memungkinkan komunikasi dupleks penuh antara klien dan server, umumnya digunakan dalam aplikasi web di mana klien dan server perlu bertukar peristiwa pada frekuensi tinggi dan dengan latensi rendah.

Spring Framework 5 telah memodernisasi dukungan WebSockets dalam framework, menambahkan kemampuan reaktif ke saluran komunikasi ini.

Kami dapat menemukan lebih banyak tentang Spring WebFlux di sini.

2. Ketergantungan Maven

Kami akan menggunakan dependensi spring-boot-starters untuk spring-boot-integration dan spring-boot-starter-webflux, yang saat ini tersedia di Spring Milestone Repository.

Dalam contoh ini, kami menggunakan versi terbaru yang tersedia, 2.0.0.M7, tetapi versi terbaru harus selalu tersedia di repositori Maven:

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

3. Konfigurasi WebSocket di Spring

Konfigurasi kami cukup mudah: Kami akan menyuntikkan WebSocketHandler untuk menangani sesi soket di aplikasi Spring WebSocket kami.

@Autowired private WebSocketHandler webSocketHandler; 

Selanjutnya, mari buat metode beranotasi kacang HandlerMapping yang akan bertanggung jawab untuk pemetaan antara permintaan dan objek handler:

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

URL yang bisa kita hubungi adalah: ws: // localhost: / event-emitter.

4. Penanganan Pesan WebSocket di Spring

Kelas ReactiveWebSocketHandler kami akan bertanggung jawab untuk mengelola sesi WebSocket di sisi server.

Ini mengimplementasikan antarmuka WebSocketHandler sehingga kita dapat mengganti metode pegangan , yang akan digunakan untuk mengirim pesan ke klien WebSocket:

@Component public class ReactiveWebSocketHandler implements WebSocketHandler { // private fields ... @Override public Mono handle(WebSocketSession webSocketSession) { return webSocketSession.send(intervalFlux .map(webSocketSession::textMessage)) .and(webSocketSession.receive() .map(WebSocketMessage::getPayloadAsText) .log()); } }

5. Membuat Klien WebSocket Reaktif Sederhana

Sekarang mari buat klien WebSocket Spring Reactive yang akan dapat menghubungkan dan bertukar informasi dengan server WebSocket kita.

5.1. Ketergantungan Maven

Pertama, dependensi Maven.

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

Di sini kami menggunakan spring-boot-starter-webflux yang sama yang digunakan sebelumnya untuk menyiapkan aplikasi server WebSocket reaktif kami.

5.2. Klien WebSocket

Sekarang, mari buat kelas ReactiveClientWebSocket , yang bertanggung jawab untuk memulai komunikasi dengan server:

public class ReactiveJavaClientWebSocket { public static void main(String[] args) throws 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)); } }

Pada kode di atas kita dapat melihat bahwa kita menggunakan ReactorNettyWebSocketClient , yang merupakan implementasi WebSocketClient untuk digunakan dengan Reactor Netty.

Selain itu, klien terhubung ke server WebSocket melalui URL ws: // localhost: 8080 / event-emitter, membuat sesi segera setelah terhubung ke server.

Kita juga dapat melihat bahwa kita mengirim pesan ke server (" event-spring-reactive-client-websocket ") bersama dengan permintaan koneksi.

Selanjutnya, metode send dipanggil, mengharapkan sebagai parameter variabel tipe Publisher, yang dalam kasus kita Publisher kita adalah Mono dan T adalah String sederhana " event-me-from-reactive-java-client-websocket ".

Selain itu, metode thenMany (…) yang mengharapkan Flux bertipe String akan dipanggil. Metode accept () mendapatkan aliran pesan masuk, yang kemudian diubah menjadi string.

Akhirnya, metode block () memaksa klien untuk memutuskan sambungan dari server setelah waktu yang ditentukan (10 detik dalam contoh kami).

5.3. Memulai Klien

Untuk menjalankannya, pastikan Server WebSocket Reaktif sudah aktif dan berjalan. Kemudian, luncurkan kelas ReactiveJavaClientWebSocket , dan kita dapat melihat di log sysout peristiwa yang sedang dipancarkan:

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

Kami juga dapat melihat di log dari server WebSocket Reaktif kami pesan yang dikirim oleh klien selama upaya koneksi:

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

Juga, kita dapat melihat pesan koneksi yang dihentikan setelah klien menyelesaikan permintaannya (dalam kasus kita, setelah 10 detik):

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

6. Membuat Klien WebSocket Browser

Mari buat klien HTML / Javascript sederhana WebSocket untuk menggunakan aplikasi server WebSocket reaktif kita.

 var clientWebSocket = new 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 = function(error) { console.log("clientWebSocket.onclose", clientWebSocket, error); events("Closing connection"); } clientWebSocket.onerror = function(error) { console.log("clientWebSocket.onerror", clientWebSocket, error); events("An error occured"); } clientWebSocket.onmessage = function(error) { console.log("clientWebSocket.onmessage", clientWebSocket, error); events(error.data); } function events(responseEvent) { document.querySelector(".events").innerHTML += responseEvent + "

"; }

Dengan server WebSocket berjalan, membuka file HTML ini di browser (misalnya: Chrome, Internet Explorer, Mozilla Firefox, dll.), Kita akan melihat peristiwa yang dicetak di layar, dengan jeda 1 detik per peristiwa, seperti yang didefinisikan dalam server WebSocket kami.

{"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. Kesimpulan

Di sini kami telah menyajikan contoh cara membuat komunikasi WebSocket antara server dan klien dengan menggunakan Spring 5 Framework, mengimplementasikan fitur reaktif baru yang disediakan oleh Spring Webflux.

Seperti biasa, contoh lengkap dapat ditemukan di repositori GitHub kami.