Un rapido esempio di annotazione @SendToUser di Spring Websockets

1. Panoramica

In questo breve tutorial, illustreremo come inviare un messaggio a una sessione specifica oa un utente particolare utilizzando Spring WebSockets .

Per un'introduzione al modulo precedente, fare riferimento a questo articolo.

2. Configurazione WebSocket

Prima di tutto, dobbiamo configurare il nostro broker di messaggi e l'endpoint dell'applicazione WebSocket :

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

Con @EnableWebSocketMessageBroker abbiamo abilitato una messaggistica supportata da broker su WebSocket utilizzando STOMP , che sta per Streaming Text Oriented Messaging Protocol. È importante sottolineare che questa annotazione deve essere utilizzata insieme a @Configuration .

Non è obbligatorio estendere AbstractWebSocketMessageBrokerConfigurer ma, per un rapido esempio, è più semplice personalizzare la configurazione importata.

Nel primo metodo, abbiamo impostato un semplice broker di messaggi basato sulla memoria per riportare i messaggi al client su destinazioni con prefisso "/ topic" e "/ queue" .

E, nel secondo, abbiamo registrato gli endpoint degli stomp in "/ greeting" .

Nel caso in cui desideriamo abilitare SockJS, dobbiamo modificare la parte del registro:

registry.addEndpoint("/greeting").withSockJS();

3. Ottieni l'ID della sessione da Interceptor

Un modo per ottenere l'id della sessione è l'aggiunta di un Spring Interceptor che verrà attivato durante l'handshake e otterrà le informazioni dai dati della richiesta.

Questo intercettore può essere aggiunto direttamente in WebSocketConfig:

@Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry .addEndpoint("/greeting") .setHandshakeHandler(new DefaultHandshakeHandler() { public boolean beforeHandshake( ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map attributes) throws Exception { if (request instanceof ServletServerHttpRequest) { ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request; HttpSession session = servletRequest .getServletRequest().getSession(); attributes.put("sessionId", session.getId()); } return true; }}).withSockJS(); }

4. WebSocket Endpoint

A partire da Spring 5.0.5.RELEASE, non è necessario eseguire alcuna personalizzazione a causa del miglioramento dell'annotazione @SendToUser , che ci consente di inviare un messaggio a una destinazione utente tramite " / user / {sessionId} / ... " piuttosto di " / user / {user} /… ".

Ciò significa che l'annotazione funziona basandosi sull'id di sessione del messaggio di input, inviando effettivamente una risposta alla destinazione privata della sessione:

@Controller public class WebSocketController { @Autowired private SimpMessageSendingOperations messagingTemplate; private Gson gson = new Gson(); @MessageMapping("/message") @SendToUser("/queue/reply") public String processMessageFromClient( @Payload String message, Principal principal) throws Exception { return gson .fromJson(message, Map.class) .get("name").toString(); } @MessageExceptionHandler @SendToUser("/queue/errors") public String handleException(Throwable exception) { return exception.getMessage(); } }

È importante sottolineare che, @SendToUser indica che il valore di ritorno di un metodo di gestione dei messaggi deve essere inviato come messaggio alle destinazioni specificate precedute da " / user / {username} " .

5. WebSocket Client

function connect() { var socket = new WebSocket('ws://localhost:8080/greeting'); ws = Stomp.over(socket); ws.connect({}, function(frame) { ws.subscribe("/user/queue/errors", function(message) { alert("Error " + message.body); }); ws.subscribe("/user/queue/reply", function(message) { alert("Message " + message.body); }); }, function(error) { alert("STOMP error " + error); }); } function disconnect() { if (ws != null) { ws.close(); } setConnected(false); console.log("Disconnected"); }

Viene creato un nuovo WebSocket che punta a " / greeting " per la mappatura in WebSocketConfiguration .

Quando iscriviamo il client a " / user / queue / errors " e " / user / queue / reply " è dove utilizziamo le informazioni rimarcate dall'ultima sezione.

Come possiamo vedere, @SendToUser punta a " queue / errors " ma il messaggio verrà inviato a " / user / queue / errors ".

6. Conclusione

In questo articolo, abbiamo esplorato un modo per inviare un messaggio direttamente a un utente o a un id di sessione con Spring WebSocket

Come sempre, il codice sorgente completo degli esempi è disponibile su GitHub.