1. 簡介
本教程將介紹如何使用 Spring WebSockets 向單個用户發送 STOMP 消息。這很重要,因為我們有時不想將每個消息廣播給所有用户。此外,我們還將演示以安全的方式發送這些消息。
對於 WebSockets 的介紹,請查看本優秀的教程,幫助您快速上手。為了更深入地瞭解安全方面,請查看本文,以安全地實現您的 WebSockets 應用程序。
2. 隊列、主題和端點
使用 Spring WebSockets 和 STOMP 有三種主要方式來指定消息發送位置以及訂閲方式:
- 主題 (Topics) – 開放給任何客户端或用户的常見對話或聊天主題
- 隊列 (Queues) – 僅供特定用户及其當前會話使用
- 端點 (Endpoints) – 通用端點
下面我們快速看一下每個端點的上下文路徑示例:
- “/topic/movies”
- “/user/queue/specific-user”
- “/secured/chat”
需要注意的是,.
3. 配置
現在,讓我們學習如何配置我們的應用程序,以便將消息發送到特定用户:
public class SocketBrokerConfig extends
WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/secured/history","/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();
}
}請務必包含用户目的地,因為這決定了哪些端點被保留給單個用户。
我們還將所有隊列和用户目的地前綴為“/secured”,以確保它們需要身份驗證。對於未受保護的端點,我們可以刪除“/secured”前綴(這是由於我們其他安全設置造成的)。
從pom.xml的角度來看,不需要添加任何額外的依賴項。
4. URL 映射
我們希望客户使用符合以下模式的 URL 映射來訂閲隊列:
"/user/queue/updates"此映射將由 UserDestinationMessageHandler 自動轉換為用户會話特定的地址。
例如,如果用户名為 “user123”,則對應的地址將是:
"/queue/updates-user123"服務端,我們將使用以下 URL 映射模式發送針對用户特定響應:
"/user/{username}/queue/updates"這也會被轉換成我們已訂閲的正確 URL 映射,用於客户端。
因此,我們看到這裏 關鍵要素是雙重性質:
- 添加我們指定的 User Destination 前綴(配置在 AbstractWebSocketMessageBrokerConfigurer 中)。
- 在映射中,使用 “/queue” 。
在下一部分,我們將詳細説明如何執行此操作。
5. 調用
我們可以非靜態地從 中調用 或 :
@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);
}你可能已經注意到:
@Header("simpSessionId") String sessionId頭 @Header 註解允許訪問 inbound 消息中暴露的頭信息。例如,我們可以無需複雜的攔截器即可獲取當前的 sessionId。 同樣,我們可以通過 Principal 訪問當前用户。
重要的是,本文采用的方法在 @sendToUser 註解上提供了更大的 URL 映射定製化程度。 欲瞭解更多關於該註解的信息,請查看這篇優秀的文章。
客户端,我們將使用 JavaScript 中的 connect() 來 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;
}
我們還訪問提供的 sessionId,並將它附加到“secured/room”URL映射中。 這使我們能夠動態地和手動地提供用户特定的訂閲隊列:
stompClient.subscribe('secured/user/queue/specific-user'
+ '-user' + that.sessionId, function (msgOut) {
//handle messages
}
一切設置完成後,我們應該看到:
以及在服務器控制枱中: