Spring WebSocket如何向特定用户发送消息?

smw*_*dia 7 spring stomp websocket

我正在阅读Spring in Action 4中的书,以便通过WebSocket处理STOMP消息传递.

假设user destination prefix is set as "/user"如下:

registry.setUserDestinationPrefix("/user");
Run Code Online (Sandbox Code Playgroud)

然后客户使用以下JavaScript代码订阅目的地:

stomp.subscribe("/user/queue/notifications", handleNotifications);
Run Code Online (Sandbox Code Playgroud)

然后在服务器上,客户端订阅的actual目标the应该从其会话派生,可能是这样的:

/queue/notifications-user6hr83v6t  --- (1)
Run Code Online (Sandbox Code Playgroud)

然后我使用SimpMessagingTemplate向该用户发送消息:

messaging.convertAndSendToUser( username, "/queue/notifications",
                           new Notification("You just got mentioned!"));
Run Code Online (Sandbox Code Playgroud)

然后消息将发送到目的地,如下所示:

/user/<username>/queue/notifications  ---(2)
Run Code Online (Sandbox Code Playgroud)

那么,两个目的地(1)(2)外观不同,怎么可能永远邮件到达客户端?

小智 5

路径

/user/<username>/queue/notifications 
Run Code Online (Sandbox Code Playgroud)

似乎是文档中使用的“逻辑”路径。它最初也是使用 convertAndSendToUser 方法创建的。然后将其转换为技术格式,该格式在此行的 UserDestinationMessageHandler 类中完成

UserDestinationResult result = this.destinationResolver.resolveDestination(message);
Run Code Online (Sandbox Code Playgroud)

例如。

鉴于订阅:

stompClient.subscribe('/user/queue/reply', function (greeting) { ...
Run Code Online (Sandbox Code Playgroud)

发送消息

stompClient.send("/app/personal", ...
Run Code Online (Sandbox Code Playgroud)

并拦截它

@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());
}
Run Code Online (Sandbox Code Playgroud)

目的地将按如下方式解析:

source destination: /user/zojdn53y/queue/reply
target destination: /queue/reply-userzojdn53y
Run Code Online (Sandbox Code Playgroud)

这就是最终目的地名称的解析方式。目标目的地是创建的队列的真实名称(至少只要使用外部消息代理 - 没有检查简单的内存代理,但我认为这将是相同的)。

需要注意的一件重要事情是,当您想使用未经身份验证的用户时(在试验 Websockets 时最常见的情况),您需要另外将消息头放在 convertAndSendToUser 方法中 - 这在

Spring WebSocket @SendToSession: send message to specific会议