Introduction : Pourquoi WebSocket est la norme pour les applications temps réel en Java
Les applications web modernes nécessitent un échange instantané de données entre le client et le serveur. Le protocole HTTP traditionnel, basé sur le modèle « requête-réponse », est peu adapté aux tâches où une latence minimale est cruciale : chats en ligne, cotations boursières, jeux multijoueurs ou tableaux de bord en temps réel.
Le protocole WebSocket résout ce problème en établissant une connexion bidirectionnelle permanente entre le client et le serveur. Après une poignée de main HTTP initiale, la connexion est « mise à niveau » vers WebSocket, et les données sont transmises sous forme de trames sans en-têtes supplémentaires. Java, grâce à sa puissante bibliothèque standard et à ses frameworks, offre d'excellents outils pour travailler avec WebSocket.
Dans cet article, nous allons voir comment créer une application temps réel complète en Java en utilisant Jakarta WebSocket API (anciennement Java EE WebSocket). Vous découvrirez la configuration du serveur, le traitement des messages, la gestion des sessions et les solutions architecturales typiques.
Fondamentaux du travail avec WebSocket en Java : Jakarta WebSocket API
Depuis Java EE 7 (Jakarta EE), la plateforme standard a intégré JSR 356 — l'API Java pour WebSocket. Cela signifie que pour créer un serveur WebSocket, il n'est pas nécessaire d'ajouter des bibliothèques tierces — un conteneur de servlets supportant Jakarta EE suffit (par exemple, Apache Tomcat 9+, Jetty 10+, WildFly).
Création d'un endpoint WebSocket
L'élément principal est une classe endpoint annotée avec @ServerEndpoint. À l'intérieur, nous définissons les méthodes qui seront appelées lors de la connexion, de la réception d'un message, d'une erreur ou de la fermeture de la connexion.
import jakarta.websocket.*;import jakarta.websocket.server.ServerEndpoint;import java.io.IOException;import java.util.Set;import java.util.concurrent.CopyOnWriteArraySet;
@ServerEndpoint("/chat")public class ChatEndpoint {
private static final Set<Session> sessions = new CopyOnWriteArraySet<>();
@OnOpen public void onOpen(Session session) { sessions.add(session); broadcast("Utilisateur connecté. Total : " + sessions.size()); }
@OnMessage public void onMessage(String message, Session session) { broadcast("[" + session.getId() + "] : " + message); }
@OnClose public void onClose(Session session) { sessions.remove(session); broadcast("Utilisateur déconnecté. Restants : " + sessions.size()); }
@OnError public void onError(Session session, Throwable throwable) { System.err.println("Erreur dans la session " + session.getId() + " : " + throwable.getMessage()); }
private void broadcast(String message) { for (Session s : sessions) { if (s.isOpen()) { try { s.getBasicRemote().sendText(message); } catch (IOException e) { e.printStackTrace(); } } } }}Dans cet exemple :
@ServerEndpoint("/chat")— indique que l'endpoint est accessible via le chemin relatif/chat.CopyOnWriteArraySet— une collection thread-safe pour stocker les sessions actives.@OnOpen— est appelé lors de l'établissement de la connexion.@OnMessage— est appelé lors de la réception d'un message texte.@OnClose— est appelé lors de la fermeture de la connexion.@OnError— gestion des erreurs.
JavaScript côté client
Pour tester le serveur, un simple fichier HTML avec JavaScript suffit :
<!DOCTYPE html><html><head> <title>WebSocket Chat</title></head><body> <div id="messages"></div> <input type="text" i