我正在阅读《Spring in Action 4》一书,以便通过WebSocket处理STOMP消息。
假设user destination prefix is set as "/user"
如下:
registry.setUserDestinationPrefix("/user");
然后客户端使用以下JavaScript代码订阅目的地:
stomp.subscribe("/user/queue/notifications", handleNotifications);
然后在服务器上,the
客户端订阅的actual
目的地应该是从其会话中派生的,可能如下所示:
/queue/notifications-user6hr83v6t --- (1)
然后我使用SimpMessagingTemplate
向该用户发送消息:
messaging.convertAndSendToUser( username, "/queue/notifications",
new Notification("You just got mentioned!"));
然后消息将被发送到如下目的地:
/user/<username>/queue/notifications ---(2)
好吧,两个目的地(1)
和(2)
看起来不一样,消息怎么会到达客户端?
路径
/user/<username>/queue/notifications
似乎是文档中使用的"逻辑"路径。它最初也是使用convertAndSendToUser方法创建的。然后,它被翻译成一种技术格式,在中的UserDestinationMessageHandler类中完成
UserDestinationResult result = this.destinationResolver.resolveDestination(message);
例如
给定订阅:
stompClient.subscribe('/user/queue/reply', function (greeting) { ...
使用发送消息
stompClient.send("/app/personal", ...
并用拦截
@MessageMapping("/personal")
public void personalMessage(SimpMessageHeaderAccessor headerAccessor, PoCRequestMessage message) {
SimpMessageHeaderAccessor ha = SimpMessageHeaderAccessor
.create(SimpMessageType.MESSAGE);
ha.setSessionId(headerAccessor.getSessionId());
ha.setLeaveMutable(true);
PoCReplyMessage reply = new PoCReplyMessage("Personal Message" + message.getName());
simpMessagingTemplate.convertAndSendToUser(headerAccessor.getSessionId(), "/queue/reply", reply, ha.getMessageHeaders());
}
目的地将按如下方式解析:
source destination: /user/zojdn53y/queue/reply
target destination: /queue/reply-userzojdn53y
这就是最终目的地名称的解析方式。目标目的地是创建的队列的真实名称(至少只要使用了外部消息代理-没有检查简单的内存代理,但我认为这是一样的)。
需要注意的一点是,当您想要使用未经身份验证的用户时(最常见的情况是在尝试Websockets时),您需要在convertAndSendToUser方法中添加消息头-这在
Spring WebSocket@SendToSession:向特定会话发送消息