Spring WebSockets: Erstellen Sie einen Benutzerchat
1. Einführung
In diesem Tutorial wird beschrieben, wieuse Spring WebSockets to send STOMP messages to a single user. ausgeführt werden. Dies ist wichtig, da wir manchmal nicht jede Nachricht an jeden Benutzer senden möchten. Außerdem zeigen wir Ihnen, wie Sie diese Nachrichten auf sichere Weise senden können.
2. Warteschlangen, Themen und Endpunkte
Es gibtthree main ways to say where messages are sent and how they are subscribed to, die Spring WebSockets und STOMP verwenden:
-
Topics - allgemeine Konversationen oder Chat-Themen, die jedem Client oder Benutzer offen stehen
-
Queues - reserviert für bestimmte Benutzer und deren aktuelle Sitzungen
-
Endpoints - generische Endpunkte
Lassen Sie uns nun einen kurzen Blick auf einen Beispielkontextpfad für jeden werfen:
-
“/topic/movies”
-
“/user/queue/specific-user”
-
“/secured/chat”
Es ist wichtig zu beachten, dass we must use queues to send messages to specific users, as topics and endpoints don’t support this functionality.
3. Aufbau
Lassen Sie uns nun lernen, wie Sie unsere Anwendung so konfigurieren, dass wir Nachrichten an einen bestimmten Benutzer senden können:
public class SocketBrokerConfig extends
AbstractWebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/secured/user/queue/specific-user");
config.setApplicationDestinationPrefixes("/spring-security-mvc-socket");
config.setUserDestinationPrefix("/secured/user");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/secured/room").withSockJS();
}
}
Stellen Sie sicher, dass Sie ein Benutzerziel angeben, da dies bestimmt, welche Endpunkte für einzelne Benutzer reserviert sind.
Außerdem stellen wir allen Warteschlangen und Benutzerzielen“/secured”vor, damit sie authentifiziert werden müssen. Bei ungeschützten Endpunkten können wir das Präfix“/secured”löschen (aufgrund unserer anderen Sicherheitseinstellungen).
Aus Sicht vonpom.xmlind keine zusätzlichen Abhängigkeiten erforderlich.
4. URL-Zuordnungen
Wir möchten, dass unser Client eine Warteschlange mit einer URL-Zuordnung abonniert, die dem folgenden Muster entspricht:
"/user/queue/updates"
Diese Zuordnung wird automatisch umUserDestinationMessageHandler in die benutzersitzungsspezifische Adresse umgewandelt.
Wenn wir beispielsweise einen Benutzer mit dem Namen“user123” haben, lautet die entsprechende Adresse:
"/queue/updates-user123"
Auf der Serverseite senden wir unsere benutzerspezifische Antwort mithilfe des folgenden URL-Zuordnungsmusters:
"/user/{username}/queue/updates"
Auch dies wird in die korrekte URL-Zuordnung umgewandelt, die wir bereits clientseitig abonniert haben.
Wir sehen also, dassthe essential ingredients here are two-fold:
-
Stellen Sie unser angegebenes Benutzerzielpräfix voran (konfiguriert inAbstractWebSocketMessageBrokerConfigurer).
-
Verwenden Sie“/queue” irgendwo in der Zuordnung.
Im nächsten Abschnitt werden wir uns genau ansehen, wie das geht.
5. convertAndSendToUser() aufrufen
Wir könnenconvertAndSendToUser() nicht statisch ausSimpMessagingTemplate oderSimpMessageSendingOperations aufrufen:
@Autowired
private SimpMessagingTemplate simpMessagingTemplate;
@MessageMapping("/secured/room")
public void sendSpecific(
@Payload Message msg,
Principal user,
@Header("simpSessionId") String sessionId) throws Exception {
OutputMessage out = new OutputMessage(
msg.getFrom(),
msg.getText(),
new SimpleDateFormat("HH:mm").format(new Date()));
simpMessagingTemplate.convertAndSendToUser(
msg.getTo(), "/secured/user/queue/specific-user", out);
}
Sie haben vielleicht bemerkt:
@Header("simpSessionId") String sessionId
The @Header annotation allows access to headers exposed by the inbound message. Zum Beispiel können wir die aktuellensessionId erfassen, ohne dass komplizierte Abfangjäger erforderlich sind. In ähnlicher Weise istwe can access the current user via Principal.
Wichtig ist, dass der in diesem Artikel verfolgte Ansatz eine bessere Anpassung der Annotation von@sendToUserin Bezug auf URL-Zuordnungen bietet. Weitere Informationen zu dieser Anmerkung finden Sie inthis's großartigem Artikel.
Auf der Clientseite verwenden wirconnect() in JavaScript bisinitialize a SockJS instance and connect to our WebSocket server using STOMP:
var socket = new SockJS('/secured/room');
var stompClient = Stomp.over(socket);
var sessionId = "";
stompClient.connect({}, function (frame) {
var url = stompClient.ws._transport.url;
url = url.replace(
"ws://localhost:8080/spring-security-mvc-socket/secured/room/", "");
url = url.replace("/websocket", "");
url = url.replace(/^[0-9]+\//, "");
console.log("Your current session is: " + url);
sessionId = url;
}
Wir greifen auch auf die bereitgestelltensessionId zu und hängen diese an die URL-Zuordnung vonsecured/room“ an. This gives us the ability to dynamically and manually supply a user-specific subscription queue:
stompClient.subscribe('secured/user/queue/specific-user'
+ '-user' + that.sessionId, function (msgOut) {
//handle messages
}
Sobald alles eingerichtet ist, sollten wir sehen:
Und in unserer Serverkonsole:
6. Fazit
Weitere Informationen zu diesem Thema finden Sie in den offiziellen Springblog undofficial documentation.
Wie immer sind die in diesem Artikel verwendeten Codebeispieleover on GitHub verfügbar.