如何将websocket消息从服务器发送给特定用户?
我的webapp具有弹簧安全设置并使用websocket。我尝试将邮件从服务器发送到仅限特定用户时遇到棘手问题。
我从阅读the manual的理解来自我们可以做的服务器
simpMessagingTemplate.convertAndSend("/user/{username}/reply", reply);
在客户端:
stompClient.subscribe('/user/reply', handler);
但我永远无法调用订阅回调。我尝试了许多不同的路径,但没有运气。
如果我将其发送到 / 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
2)导航到http://localhost:8080
,使用bob / test或jim / test登录
3)点击"请求用户特定的消息"。预期:一条消息" hello {username}"显示在"仅收到消息给我的旁边"仅限此用户,实际:未收到任何内容
答案 0 :(得分:62)
哦,client side no need to known about current user
,服务器会为你做这件事。
在服务器端,使用以下方式向用户发送消息:
simpMessagingTemplate.convertAndSendToUser(username, "/queue/reply", message);
注意:使用queue
而不是topic
,Spring总是使用queue
1>}
在客户端
sendToUser
<强>解释强>
当打开任何websocket连接时,Spring会为其分配stompClient.subscribe("/user/queue/reply", handler);
(不是session id
,为每个连接分配)。当您的客户端订阅以HttpSession
开头的频道时,例如:/user/
,您的服务器实例将订阅名为/user/queue/reply
的队列
使用时向用户发送消息,例如:用户名为queue/reply-user[session id]
你会写admin
Spring将确定哪个simpMessagingTemplate.convertAndSendToUser("admin", "/queue/reply", message);
映射到用户session id
。例如:它找到了两个会话admin
和wsxedc123
,Spring会将其转换为2个目标thnujm456
和queue/reply-userwsxedc123
,并将您的消息与2个目的地发送给您的消息代理。
消息代理接收消息并将其提供回服务器实例,该实例持有与每个会话相对应的会话(WebSocket会话可由一个或多个服务器保存)。 Spring会将消息转换为queue/reply-userthnujm456
(例如:destination
)和user/queue/reply
(例如:session id
)。然后,它将消息发送到相应的wsxedc123
答案 1 :(得分:28)
啊,我发现了我的问题。首先,我没有在简单经纪人
上注册/user
前缀
<websocket:simple-broker prefix="/topic,/user" />
然后我在发送时不需要额外的/user
前缀:
convertAndSendToUser(principal.getName(), "/reply", reply);
Spring会自动将"/user/" + principal.getName()
添加到目的地,因此它会解析为“/ user / bob / reply”。
这也意味着在javascript中我必须为每个用户订阅不同的地址
stompClient.subscribe('/user/' + userName + '/reply,...)
答案 2 :(得分:2)
我的解决方案基于Thanh Nguyen Van的最佳解释,但另外我已经配置了MessageBrokerRegistry:
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/queue/", "/topic/");
...
}
...
}
答案 3 :(得分:2)
我也使用STOMP创建了一个示例websocket项目。 我注意到的是
classpathScope
}
无论是否&#34; / user&#34;包含在config.enableSimpleBroker(...
中答案 4 :(得分:2)
我确实做了同样的事情而且没有使用用户
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/gs-guide-websocket").withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic" , "/queue");
config.setApplicationDestinationPrefixes("/app");
}
}