Jeudi 24, Août 2023
Recherche sur les WebSockets en Java Framework (Spring Boot)
WebSocket : Définition
WebSocket est un protocole de communication qui offre une communication bidirectionnelle en
temps réel entre le client et le serveur sur une seule connexion longue durée. Il est conçu pour être
implémenté dans les navigateurs web et les serveurs web, mais peut être utilisé par n'importe quel
client ou serveur d'application.
Pourquoi est-il nécessaire?
Traditionnellement, la communication web utilisait le protocole HTTP, qui est un protocole sans
état basé sur une demande-réponse. Cela signifie que chaque fois qu'une donnée doit être transférée,
le client (généralement un navigateur) envoie une demande au serveur, qui répond en retour. Pour
des applications nécessitant une mise à jour en temps réel, telles que les jeux en ligne, les chats en
direct, les applications de trading, etc., ce modèle n'est pas optimal car il peut introduire des
latences.
WebSocket a été introduit pour permettre aux applications web d'avoir des interactions en temps
réel sans avoir à recourir à des solutions de contournement telles que le "polling" (où le client
demande régulièrement des mises à jour au serveur).
Caractéristiques principales :
1. Communication bidirectionnelle : Contrairement au modèle de demande-réponse d'HTTP,
où le client initie toujours la communication, WebSocket permet à la fois au client et au
serveur d'envoyer des données à tout moment.
2. Connexion persistante : Une fois qu'une connexion WebSocket est établie, elle reste
ouverte, permettant la communication continue entre le client et le serveur.
3. Faible latence : Étant donné qu'il n'y a pas besoin de rétablir une connexion à chaque fois
qu'une donnée est échangée, les WebSockets peuvent offrir des communications en temps
réel avec une latence minimale.
[Link] dans HTTP : Le processus d'établissement d'une connexion WebSocket
commence par une "poignée de main" basée sur HTTP. Cela signifie que les WebSockets peuvent
fonctionner sur le même port qu'HTTP et peuvent bénéficier des fonctionnalités d'HTTP telles que
les cookies et les headers.
• Efficacité en termes de bande passante : Contrairement au "polling", où des données
peuvent être demandées même lorsqu'il n'y a pas de mises à jour, WebSocket utilise la bande
passante uniquement lorsqu'il y a des données à transmettre.
Utilisations courantes :
• Applications de chat : Pour les chats en direct, la mise à jour instantanée est essentielle.
WebSocket est souvent utilisé pour cela.
• Jeux en ligne : La faible latence offerte par WebSocket est bénéfique pour les jeux en ligne.
• Notifications en temps réel : Par exemple, informer un utilisateur lorsqu'un nouvel article
est publié.
• Applications de trading : Mise à jour en temps réel des prix des actions.
• Applications de sport : Mise à jour des scores et des événements en temps réel.
Projet de recherche et de compréhension :
ChatApp : ChatApp est un projet spring conçu pour tester et appliquer les notions de websocket
en java.
Interface d’accueil de ChatApp à la première page il nous est demandé de saisir notre nom
d’utilisateur pour entrer dans le forum de discussion, ici notre User se nomme «MAKEN» .
Une fois
entré dans
le forum
de
discussion
nous
avons la
boite de
dialogue
ouverte et
un
message
qui signale
un
nouvelle
arrivant
dans la
discussion
aux autres
Users.
Ici on signale au User leonel qu’un nouvelle user du nom de Maken a rejoint la discussion.
Simulation de discussion.
EXPLICATION ET DESCRIPTION DU CODE SOURCE
Ici nous avons 6 fichiers principaux parmi lesquels :
➢ Le WebSocketListener :
Il gère les déconnexions WebSocket pour informer d'autres utilisateurs qu'un utilisateur s'est
déconnecté. Voici une explication détaillée de chaque partie :
1. Annotations et imports :
• @Component: Indique que cette classe est un composant Spring, et elle sera
automatiquement détectée lors du balayage de composants.
• @RequiredArgsConstructor: Une annotation Lombok qui génère automatiquement
un constructeur avec des paramètres requis (final ou @NonNull).
• @Slf4j: Une annotation Lombok qui génère un logger pour la classe.
2. Variables Membres :
• SimpMessageSendingOperations messagingTemplate: C'est une interface
fournie par Spring pour envoyer des messages à travers WebSockets. Cependant, elle est
initialisée à null, ce qui est étrange car cela provoquera une NullPointerException
si on essaie de l'utiliser.
3. La méthode handleWebSocketDisconnectListener :
• Elle est annotée avec @EventListener, ce qui signifie qu'elle sera appelée chaque fois
qu'un SessionDisconnectEvent est publié dans le contexte Spring.
• Cette méthode extrait le nom d'utilisateur de l'événement, enregistre la déconnexion et
envoie un message pour informer que l'utilisateur s'est déconnecté.
4. La méthode handleWebSocketDisconnectListener :
• Elle est annotée avec @EventListener, ce qui signifie qu'elle sera appelée chaque fois
qu'un SessionDisconnectEvent est publié dans le contexte Spring.
• Cette méthode extrait le nom d'utilisateur de l'événement, enregistre la déconnexion et
envoie un message pour informer que l'utilisateur s'est déconnecté.
5. La méthode logDisconnection :
• Elle prend un nom d'utilisateur en entrée et enregistre simplement une information indiquant
que l'utilisateur s'est déconnecté.
6. La méthode logDisconnection :
• Elle prend un nom d'utilisateur en entrée et enregistre simplement une information indiquant
que l'utilisateur s'est déconnecté.
7. La méthode sendUserLeftMessage :
• Elle crée un message de type "LEAVER" et l'envoie sur le topic "/topic/public" via
WebSockets pour informer d'autres utilisateurs qu'un utilisateur s'est déconnecté.
8. La méthode createLeaveMessage :
• Crée un nouvel objet ChatMessage avec le type "LEAVER" et le nom d'utilisateur
comme expéditeur.
Globalement, ce composant écoute les déconnexions WebSocket, et chaque fois qu'un
utilisateur se déconnecte, il informe les autres utilisateurs de la déconnexion.
➢ [Link]
Une énumération (ou enum) est un type spécial en Java qui représente un groupe de constantes.
Dans ce cas, MessageType représente trois types de messages possibles pour une application de
chat :
1. CHAT : Cela pourrait représenter un message de chat standard où un utilisateur envoie un
message à d'autres utilisateurs.
2. JOIN : Ceci pourrait indiquer qu'un utilisateur a rejoint le chat ou la salle de chat.
3. LEAVER : Comme son nom l'indique, cela pourrait signifier qu'un utilisateur a quitté le
chat ou la salle de chat.
Lors de la modélisation d'une application de chat, ces types de messages peuvent être utilisés pour
déterminer le type d'action à effectuer ou comment traiter un message entrant. Par exemple, si le
type de message est JOIN, l'interface utilisateur pourrait afficher un message comme "John a
rejoint le chat". Si le type est LEAVER, elle pourrait afficher "John a quitté le chat".
La combinaison de cette énumération avec le code précédent montre comment l'application traite
les déconnexions d'utilisateurs : en envoyant un message de type LEAVER à d'autres utilisateurs
pour les informer qu'un utilisateur s'est déconnecté.
➢ ChatMessage
Ce bout de code définit une classe Java appelée ChatMessage dans le package
[Link]. La classe représente un message dans un système de chat. Voici une explication
détaillée de chaque partie :
1. Annotations Lombok :
• @AllArgsConstructor: génère un constructeur avec un argument pour chaque
champ de la classe.
• @NoArgsConstructor: génère un constructeur sans argument.
• @Getter: génère des getters pour tous les champs.
• @Setter: génère des setters pour tous les champs.
• @Builder: permet de construire des objets avec un pattern builder.
Notez que malgré la présence de ces annotations, le code contient des constructeurs, getters
et setters manuellement codés, ce qui rend ces annotations redondantes.
2. Champs de la classe :
• private String content: représente le contenu du message.
• private String sender: représente l'expéditeur du message.
• private MessageType type: indique le type de message, en utilisant
l'énumération MessageType que vous avez montrée précédemment.
3. Constructeurs :
• ChatMessage(String content, String sender, MessageType
type): un constructeur avec des arguments pour initialiser les champs content,
sender et type.
4. Getters et Setters : Ces méthodes permettent d'obtenir ou de définir les valeurs des champs
privés de la classe.
En conclusion, cette classe représente un message dans un chat, avec des informations sur le
contenu du message, l'expéditeur et le type de message.
➢ WebSocketConfig :
Ce code est une configuration Spring qui définit comment les WebSockets fonctionnent dans
votre application. Il est spécifiquement axé sur la configuration de STOMP, qui est un
protocole simple pour la messagerie orientée message. Spring fournit une prise en charge
pour STOMP sur WebSockets, et ce code configure cette prise en charge. Voici une
explication détaillée :
2. Annotations :
• @Configuration : Indique que cette classe est une classe de configuration
Spring. Elle est utilisée pour définir des beans et des configurations.
• @EnableWebSocketMessageBroker : Active le support de courtage de
messages basé sur WebSocket dans l'application.
3. Interface WebSocketMessageBrokerConfigurer :
• La classe WebSocketConfig implémente cette interface pour fournir des
configurations personnalisées pour les WebSockets.
4. Méthode registerStompEndpoints :
• Cette méthode est utilisée pour enregistrer les points de terminaison STOMP que les
clients WebSocket utiliseront pour se connecter à votre serveur.
• [Link]("/ws").withSockJS();: Ajoute un point de
terminaison STOMP à l'URL /ws et le configure pour utiliser SockJS.
• SockJS est une bibliothèque JavaScript qui fournit un mécanisme de repli
pour les navigateurs qui ne prennent pas en charge les WebSockets. Cela
signifie que si un client ne peut pas utiliser les WebSockets natifs pour une
raison quelconque, SockJS fournira des alternatives comme les longs
sondages AJAX.
5. Méthode configureMessageBroker :
• Cette méthode est utilisée pour configurer le courtier de messages qui relaiera les
messages entre les clients et les serveurs.
• [Link]("/app");: Définit
le préfixe pour les destinations qui sont destinées à être gérées par les méthodes
annotées par @MessageMapping dans vos contrôleurs. Par exemple, si vous avez
un contrôleur qui traite les messages envoyés à /app/chat, il gérerait les messages
destinés à ce chemin.
• [Link]("/topic");: Active un courtier de
messages simple en mémoire. Les messages adressés aux destinations commençant
par /topic seront relayés aux abonnés de ces destinations. C'est utile pour des
scénarios de publication/abonnement.
En conclusion, ce code configure votre application pour utiliser STOMP sur WebSockets. Il définit
un point de terminaison à /ws pour les connexions WebSocket et configure un simple courtier de
messages pour gérer les destinations commençant par /topic.
➢ ChatController
Ce code définit un contrôleur Spring qui gère les messages de chat reçus via WebSocket. Voici une
explication détaillée de chaque partie :
1. Annotations :
• @Controller: Cette annotation indique que cette classe est un contrôleur Spring.
Elle est généralement utilisée pour définir les beans qui géreront les requêtes HTTP,
mais dans ce contexte, elle est utilisée pour un contrôleur de messagerie WebSocket.
2. Méthode sendMessage :
• @MessageMapping("/[Link]"): Cette annotation indique que
cette méthode doit être appelée lorsqu'un message est envoyé à la destination
/[Link].
• @SendTo("/topic/public"): Après avoir traité le message, le résultat (dans
ce cas, le ChatMessage original) sera envoyé à la destination /topic/public.
• Le paramètre @Payload ChatMessage chatMessage: L'annotation
@Payload extrait le corps du message et le mappe à l'objet ChatMessage. En
d'autres termes, le message entrant est automatiquement converti en un objet
ChatMessage.
3. Méthode addUser :
• @MessageMapping("/[Link]"): Cette méthode doit être appelée
lorsqu'un message est envoyé à la destination /[Link].
• @SendTo("/topic/public"): De la même manière que précédemment, après
avoir traité le message, le résultat est envoyé à la destination /topic/public.
• Le paramètre @Payload ChatMessage chatMessage: Comme avant, cela
mappe le corps du message à l'objet ChatMessage.
• SimpMessageHeaderAccessor headerAccessor: C'est un accesseur pour
accéder aux en-têtes du message. Il est utilisé ici pour accéder aux attributs de la
session et y ajouter le nom d'utilisateur.
• Dans le corps de la méthode addUser, vous pouvez voir que le code ajoute le nom
de l'expéditeur du ChatMessage aux attributs de la session avec la clé
"username". Cela implique que chaque fois qu'un utilisateur rejoint le chat, son
nom d'utilisateur est stocké dans la session, probablement pour une utilisation
ultérieure (comme le suivi de qui est connecté).
En conclusion, ce contrôleur gère deux types de messages: l'envoi de messages de chat et l'ajout de
nouveaux utilisateurs au chat. Les messages sont traités par les méthodes appropriées en fonction de
la destination à laquelle ils sont envoyés, puis le résultat est transmis à tous les abonnés de la
destination /topic/public.