Introduction aux WebSockets avec Spring

1. Vue d'ensemble

Dans cet article, nous allons créer une application Web simple qui implémente la messagerie à l'aide des nouvelles fonctionnalités WebSocket introduites avec Spring Framework 4.0.

WebSockets est un bi-directionnel , full-duplex , connexion persistante entre un navigateur Web et un serveur. Une fois qu'une connexion WebSocket est établie, la connexion reste ouverte jusqu'à ce que le client ou le serveur décide de fermer cette connexion.

Un cas d'utilisation typique pourrait être lorsqu'une application implique plusieurs utilisateurs communiquant entre eux, comme dans une discussion. Nous allons créer un client de chat simple dans notre exemple.

2. Dépendances de Maven

Puisqu'il s'agit d'un projet basé sur Maven, nous ajoutons d'abord les dépendances requises au pom.xml :

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

De plus, comme nous utiliserons JSON pour créer le corps de nos messages, nous devons ajouter les dépendances Jackson . Cela permet à Spring de convertir notre objet Java vers / depuis JSON :

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

Si vous souhaitez obtenir la dernière version des bibliothèques ci-dessus, recherchez-les sur Maven Central.

3. Activez WebSocket au printemps

La première chose à faire est d'activer les fonctionnalités WebSocket. Pour ce faire, nous devons ajouter une configuration à notre application et annoter cette classe avec @EnableWebSocketMessageBroker .

Comme son nom l'indique, il permet la gestion des messages WebSocket, soutenue par un courtier de messages:

@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(); } } 

Ici, nous pouvons voir que la méthode configureMessageBroker est utilisée pour configurer le courtier de messages . Tout d'abord, nous permettons à un courtier de messages en mémoire de ramener les messages au client sur des destinations préfixées par «/ topic».

Nous complétons notre configuration simple en désignant le préfixe «/ app» pour filtrer les destinations en ciblant les méthodes annotées par l'application (via @MessageMapping ).

La registerStompEndpoints méthode enregistre le point final « / chat », ce qui permet le soutien STOMP de printemps . Gardez à l'esprit que nous ajoutons également ici un point de terminaison qui fonctionne sans SockJS pour des raisons d'élasticité.

Ce point de terminaison, lorsqu'il est préfixé par «/ app», est le point de terminaison que la méthode ChatController.send () est mappée pour gérer.

Il active également les options de secours SockJS, de sorte que d'autres options de messagerie peuvent être utilisées si les WebSockets ne sont pas disponibles. Ceci est utile car WebSocket n'est pas encore pris en charge dans tous les navigateurs et peut être exclu par des proxys réseau restrictifs.

Les solutions de secours permettent aux applications d'utiliser une API WebSocket mais se dégradent gracieusement en alternatives non WebSocket lorsque cela est nécessaire au moment de l'exécution.

4. Créez le modèle de message

Maintenant que nous avons configuré le projet et configuré les fonctionnalités WebSocket, nous devons créer un message à envoyer.

Le point de terminaison acceptera les messages contenant le nom de l'expéditeur et un texte dans un message STOMP dont le corps est un objet JSON .

Le message pourrait ressembler à ceci:

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

Pour modéliser le message portant le texte, nous pouvons créer un simpleObjet Java avec des propriétés from et text :

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

Par défaut, Spring utilisera la bibliothèque Jackson pour convertir notre objet modèle vers et depuis JSON.

5. Créer un contrôleur de messagerie

Comme nous l'avons vu, l'approche de Spring pour travailler avec la messagerie STOMP consiste à associer une méthode de contrôleur au point de terminaison configuré. Ceci est rendu possible grâce à l' annotation @MessageMapping .

L'association entre le point de terminaison et le contrôleur nous donne la possibilité de gérer le message si nécessaire:

@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); } 

F or the purposes of our example, we'll create another model object named OutputMessage to represent the output message sent to the configured destination . We populate our object with the sender and the message text taken from the incoming message and enrich it with a timestamp.

After handling our message, we send it to the appropriate destination defined with the @SendTo annotation. All subscribers to the “/topic/messages” destination will receive the message.

6. Create a Browser Client

After making our configurations in the server-side, we'll use the sockjs-client library to build a simple HTML page that interacts with our messaging system.

First of all, we need to import the sockjs and stomp Javascript client libraries. Next, we can create a connect() function to open the communication with our endpoint, a sendMessage() function to send our STOMP message and a disconnect() function to close the communication:

  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. Testing the Example

To test our example, we can open a couple of browser windows and access the chat page at:

//localhost:8080

Once this is done, we can join the chat by entering a nickname and hitting the connect button. If we compose and send a message we can see it in all browser sessions that have joined the chat.

Take a look at the screenshot to see an example:

8. Conclusion

Dans ce didacticiel, nous avons exploré le support WebSocket de Spring. Nous avons vu sa configuration côté serveur et construit une contrepartie simple côté client avec l'utilisation de bibliothèques Javascript sockjs et stomp .

L'exemple de code se trouve dans le projet GitHub.