无法使用Spring Websocket STOMP向特定用户发送消息

3
我正在尝试使用Spring WebSocket和Stomp创建一个聊天应用程序。 我使用的是Spring 4.1.1、Stomp.js和ActiveMQ 5.9。 在这个应用程序中,用户可以通过登录向他/她的好友发送消息。 要向特定的用户发送消息,我采取以下步骤: 1) 用户登录 2) 用户订阅"/user/queue/messaging"目的地。 这将用于将用户的私人消息发送给彼此。 3) 当用户想要发送消息时,他将其发送到目的地: /user/{user_id}/queue/messaging,其中user_id是接收者的用户ID。 我正在尝试使用STOMP.js send方法从客户端发送此消息。 4) 预期行为: 现在,如果接收者已登录且其会话ID(例如DFT0GH), 则步骤e中的消息应传递到名称为messaging-userDFT0GH的队列目的地。但实际上它被发送到了发送者的队列目的地。
请查看我的示例场景: 1) 用户John登录。 他订阅/user/queue/messaging。 他的用户ID是john。 他的会话ID是ABCD01。 在activemq代理服务器上,队列的名称为messaging-userABCD01。
2) 用户Alice登录。 她订阅/user/queue/messaging。 她的用户ID是alice。 她的会话ID是XYZ01。 在activemq代理服务器上,队列的名称为messaging-userXYZ01。
3) 用户John使用STOMP.js send方法向Alice发送消息, 目标为"/user/alice/queue/messaging"。
4) 现在,消息不是传递到队列messaging-UserXYZ01, 而是被传递到John的队列目的地,即messaging-userABCD01。为什么会这样呢?
当我调试时,在DefaultUserDestinationResolver类的parseUserDestination(Message message)方法中找到了以下行:
  if (SimpMessageType.MESSAGE.equals(messageType)) {
        ........
    sessionIds = (sessionId != null ?
                Collections.singleton(sessionId) : this.userSessionRegistry.getSessionIds(user));      
    }

在这里,sessionId是已登录用户的(Principal)会话ID,因为用户已登录,所以他的sessionIds被返回并将消息传递到他的队列,即使预期的接收方用户不同也是如此。
当我检查usersessionregistry的sessionIds集合时,我发现一个条目[alice]:XYZ01。
如果用户使用已登录用户的会话而不是会话ID来识别目标队列,上述行不应该返回会话ID吗?

对不起,这是我第一次尝试。因此,请告诉我是否漏掉了任何内容,以及是否有
1)任何满足我的用例的方法
2)或者我的用例本身无效。

提前感谢。


似乎是自Spring 4.1.0版本以来引入的一个错误。以下是我打开的JIRA链接:https://jira.spring.io/browse/SPR-12444 - Shailesh Vaishampayan
1个回答

2
只是为了避免这个问题留在未回答的列表中 - 这确实是一个错误,您将其提出作为 SPR-12444
这将在Spring Framework 4.1.3中修复。
另外,我想指出,如果您正在部署具有多个实例的应用程序,则会话注册表默认情况下不在实例之间共享 - 因此,当从alice(具有到服务器#1的会话)发送消息到bob(到服务器#2的会话)时,这将导致问题。

感谢Brian提供的额外信息。 - Shailesh Vaishampayan
嗨,布莱恩,我对你回答中的第二个要点很感兴趣,但我不明白你的意思。你提到的示例发送消息的方式是“simpMessagingTemplate.convertAndSend("/user/" + username + "/queue/chat.message", message);”。这与问题描述中所述的John通过/user/alice/queue/messaging向alice发送消息的方法有何不同? - Marios
是的,对不起 - 我会重新审视这个答案并提供更准确的内容。 - Brian Clozel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接