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

时间:2014-03-13 01:14:03

标签: java spring spring-mvc spring-websocket

如何将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}"显示在"仅收到消息给我的旁边"仅限此用户,实际:未收到任何内容

5 个答案:

答案 0 :(得分:62)

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

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

simpMessagingTemplate.convertAndSendToUser(username, "/queue/reply", message);

注意:使用queue而不是topic,Spring总是使用queue }

在客户端

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。例如:它找到了两个会话adminwsxedc123,Spring会将其转换为2个目标thnujm456queue/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");
    }
}