Introduzione a WebSocket con Spring

1. Panoramica

In questo articolo creeremo una semplice applicazione web che implementa la messaggistica utilizzando le nuove funzionalità WebSocket introdotte con Spring Framework 4.0.

WebSocket è una connessione bidirezionale , full-duplex e persistente tra un browser Web e un server. Una volta stabilita una connessione WebSocket, la connessione rimane aperta fino a quando il client o il server non decide di chiuderla.

Un tipico caso d'uso potrebbe essere quando un'app coinvolge più utenti che comunicano tra loro, come in una chat. Costruiremo un semplice client di chat nel nostro esempio.

2. Dipendenze di Maven

Poiché si tratta di un progetto basato su Maven, aggiungiamo prima le dipendenze richieste al pom.xml :

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

Inoltre, poiché utilizzeremo JSON per costruire il corpo dei nostri messaggi, dobbiamo aggiungere le dipendenze di Jackson . Ciò consente a Spring di convertire il nostro oggetto Java in / da JSON :

 com.fasterxml.jackson.core jackson-core 2.10.2   com.fasterxml.jackson.core jackson-databind 2.10.2 

Se desideri ottenere la versione più recente delle librerie di cui sopra, cercale su Maven Central.

3. Abilitare WebSocket in primavera

La prima cosa da fare è abilitare le funzionalità WebSocket. Per fare ciò dobbiamo aggiungere una configurazione alla nostra applicazione e annotare questa classe con @EnableWebSocketMessageBroker .

Come suggerisce il nome, abilita la gestione dei messaggi WebSocket, supportata da un broker di messaggi:

@Configuration @EnableWebSocketMessageBroker public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry config) { config.enableSimpleBroker("/topic"); config.setApplicationDestinationPrefixes("/app"); } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/chat"); registry.addEndpoint("/chat").withSockJS(); } } 

Qui, possiamo vedere che il metodo configureMessageBroker viene utilizzato per configurare il broker di messaggi . Innanzitutto, abilitiamo un broker di messaggi in memoria per riportare i messaggi al client su destinazioni con prefisso "/ topic".

Completiamo la nostra semplice configurazione designando il prefisso "/ app" per filtrare le destinazioni mirate ai metodi annotati dell'applicazione (tramite @MessageMapping ).

Il registerStompEndpoints metodo registra l'endpoint “/ chiacchierata”, consentendo il supporto STOMP di primavera . Tieni presente che stiamo aggiungendo anche qui un endpoint che funziona senza SockJS per motivi di elasticità.

Questo endpoint, se preceduto da "/ app", è l'endpoint che il metodo ChatController.send () è mappato per gestire.

Abilita anche le opzioni di fallback di SockJS, in modo che le opzioni di messaggistica alternative possano essere utilizzate se WebSocket non sono disponibili. Ciò è utile poiché WebSocket non è ancora supportato in tutti i browser e potrebbe essere precluso da proxy di rete restrittivi.

I fallback consentono alle applicazioni di utilizzare un'API WebSocket, ma degradano gradualmente a alternative non WebSocket quando necessario in fase di esecuzione.

4. Creare il modello di messaggio

Ora che abbiamo impostato il progetto e configurato le funzionalità di WebSocket, dobbiamo creare un messaggio da inviare.

L'endpoint accetterà messaggi contenenti il ​​nome del mittente e un testo in un messaggio STOMP il cui corpo è un oggetto JSON .

Il messaggio potrebbe essere simile a questo:

{ "from": "John", "text": "Hello!" } 

Per modellare il messaggio che trasporta il testo, possiamo creare un sempliceOggetto Java con proprietà from e text :

public class Message { private String from; private String text; // getters and setters } 

Per impostazione predefinita, Spring utilizzerà la libreria Jackson per convertire il nostro oggetto modello in e da JSON.

5. Creare un controller per la gestione dei messaggi

Come abbiamo visto, l'approccio di Spring per lavorare con la messaggistica STOMP consiste nell'associare un metodo controller all'endpoint configurato. Ciò è reso possibile tramite l' annotazione @MessageMapping .

L'associazione tra l'endpoint e il controller ci dà la possibilità di gestire il messaggio se necessario:

@MessageMapping("/chat") @SendTo("/topic/messages") public OutputMessage send(Message message) throws Exception { String time = new SimpleDateFormat("HH:mm").format(new Date()); return new OutputMessage(message.getFrom(), message.getText(), time); } 

Per gli scopi del nostro esempio, creeremo un altro oggetto modello denominato OutputMessage per rappresentare il messaggio di output inviato alla destinazione configurata. Popoliamo il nostro oggetto con il mittente e il testo del messaggio tratto dal messaggio in arrivo e lo arricchiamo con un timestamp.

Dopo aver gestito il nostro messaggio, lo inviamo alla destinazione appropriata definita con l' annotazione @SendTo . Tutti gli iscritti alla destinazione " / topic / messages " riceveranno il messaggio.

6. Creare un client browser

Dopo aver effettuato le nostre configurazioni lato server, utilizzeremo la libreria sockjs-client per creare una semplice pagina HTML che interagisce con il nostro sistema di messaggistica.

Prima di tutto, dobbiamo importare le librerie del client sockjs e calpestare Javascript. Successivamente, possiamo creare una funzione connect () per aprire la comunicazione con il nostro endpoint, una funzione sendMessage () per inviare il nostro messaggio STOMP e una funzione disconnect () per chiudere la comunicazione:

  Chat WebSocket    var stompClient = null; function setConnected(connected) { document.getElementById('connect').disabled = connected; document.getElementById('disconnect').disabled = !connected; document.getElementById('conversationDiv').style.visibility = connected ? 'visible' : 'hidden'; document.getElementById('response').innerHTML = ''; } function connect() { var socket = new SockJS('/chat'); stompClient = Stomp.over(socket); stompClient.connect({}, function(frame) { setConnected(true); console.log('Connected: ' + frame); stompClient.subscribe('/topic/messages', function(messageOutput) { showMessageOutput(JSON.parse(messageOutput.body)); }); }); } function disconnect() { if(stompClient != null) { stompClient.disconnect(); } setConnected(false); console.log("Disconnected"); } function sendMessage() { var from = document.getElementById('from').value; var text = document.getElementById('text').value; stompClient.send("/app/chat", {}, JSON.stringify({'from':from, 'text':text})); } function showMessageOutput(messageOutput) { var response = document.getElementById('response'); var p = document.createElement('p'); p.style.wordWrap = 'break-word'; p.appendChild(document.createTextNode(messageOutput.from + ": " + messageOutput.text + " (" + messageOutput.time + ")")); response.appendChild(p); }

Connect Disconnect

Send

7. Testare l'esempio

Per testare il nostro esempio, possiamo aprire un paio di finestre del browser e accedere alla pagina della chat su:

//localhost:8080

Fatto ciò, possiamo unirci alla chat inserendo un nickname e premendo il pulsante di connessione. Se componiamo e inviamo un messaggio possiamo vederlo in tutte le sessioni del browser che hanno aderito alla chat.

Dai un'occhiata allo screenshot per vedere un esempio:

8. Conclusione

In questo tutorial, abbiamo esplorato il supporto WebSocket di Spring. Abbiamo visto la sua configurazione lato server e costruito una semplice controparte lato client con l'uso di sockjs e librerie Javascript stomp .

Il codice di esempio può essere trovato nel progetto GitHub.