在Spring Websocket上向特定用户发送消息

ger*_*tan 72 java spring spring-mvc spring-websocket

如何仅从服务器向特定用户发送websocket消息?

我的webapp具有弹簧安全设置并使用websocket.我遇到了一个棘手的问题,试图从服务器向特定用户发送消息.

我阅读本手册的理解来自我们可以做的服务器

simpMessagingTemplate.convertAndSend("/user/{username}/reply", reply);
Run Code Online (Sandbox Code Playgroud)

在客户端:

stompClient.subscribe('/user/reply', handler);
Run Code Online (Sandbox Code Playgroud)

但我永远无法调用订阅回调.我尝试了许多不同的路径,但没有运气.

如果我将它发送到/ topic/reply它可以工作,但所有其他连接的用户也会收到它.

为了说明问题,我在github上创建了这个小项目:https://github.com/gerrytan/wsproblem

重现步骤:

1)克隆并构建项目(确保您使用的是jdk 1.7和maven 3.1)

$ git clone https://github.com/gerrytan/wsproblem.git
$ cd wsproblem
$ mvn jetty:run
Run Code Online (Sandbox Code Playgroud)

2)导航到http://localhost:8080,使用bob/test或jim/test登录

3)单击"请求用户特定消息".预期:仅对此用户的"仅收到消息给我"旁边显示消息"hello {username}",实际:未收到任何消息

Tha*_*Van 71

哦,client side no need to known about current user服务器会为你做那件事.

在服务器端,使用以下方式向用户发送消息:

simpMessagingTemplate.convertAndSendToUser(username, "/queue/reply", message);
Run Code Online (Sandbox Code Playgroud)

注意:使用queue,不topic,春天总是使用queuesendToUser

在客户端

stompClient.subscribe("/user/queue/reply", handler);
Run Code Online (Sandbox Code Playgroud)

说明

当任何websocket连接打开时,Spring将为其分配一个session id(不是HttpSession,为每个连接分配).当您的客户端订阅以/user/例如:开头的频道时/user/queue/reply,您的服务器实例将订阅一个名为的队列queue/reply-user[session id]

当使用发送消息给用户时,例如:用户名是admin 你将写simpMessagingTemplate.convertAndSendToUser("admin", "/queue/reply", message);

Spring将确定哪个session id映射到用户admin.例如:它发现了两个会议wsxedc123thnujm456,Spring将它翻译成2目的地queue/reply-userwsxedc123queue/reply-userthnujm456,并将其与2个目的地的消息代理发送邮件.

消息代理接收消息并将其提供回服务器实例,该实例持有与每个会话相对应的会话(WebSocket会话可由一个或多个服务器保存).Spring会将消息转换为destination(例如:) user/queue/replysession id(例如:)wsxedc123.然后,它将消息发送到相应的Websocket session

  • 你能解释一下你如何知道用户名吗?在你的例子中你说用户名是'admin',你收到用户的用户名? (6认同)
  • 请您提供有关如何设置用户名的更多信息?我可以在订阅消息上发送用户名吗? (2认同)
  • 你的解释很有效。但是官方文档中的“queue/reply-user[session id]”部分在哪里? (2认同)

ger*_*tan 31

啊,我发现了我的问题.首先,我没有/user在简单代理上注册前缀

<websocket:simple-broker prefix="/topic,/user" />
Run Code Online (Sandbox Code Playgroud)

然后我/user发送时不需要额外的前缀:

convertAndSendToUser(principal.getName(), "/reply", reply);
Run Code Online (Sandbox Code Playgroud)

Spring将自动添加"/user/" + principal.getName()到目标,因此它解析为"/ user/bob/reply".

这也意味着在javascript中我必须为每个用户订阅不同的地址

stompClient.subscribe('/user/' + userName + '/reply,...) 
Run Code Online (Sandbox Code Playgroud)

  • 嗯......有没有办法避免设置userName客户端?通过更改该值(例如,使用其他用户名),您将能够看到其他人的消息. (3认同)
  • 请参阅我的解决方案:http://stackoverflow.com/questions/25646671/check-auth-while-sending-a-message-to-a-specific-user-by-using-stomp-and-websock/25647822#25647822 (2认同)