Spring Stomp @SubscribeMapping用户目的地

时间:2014-07-22 14:42:17

标签: stomp spring-websocket

当用户使用@SubscribeMapping注释订阅stomp用户目标时,我试图收到通知。我的想法是在它加入时发送一些初始化数据。

虽然我无法正常工作:

使用Javascript:

stompClient.subscribe('/user/monitor', function(msg) {
            console.log(msg);    
        });

Java方面:

@SubscribeMapping("/monitor-user{clientId}")
public void init(@DestinationVariable("clientId") String clientId) {
    messagingTemplate.convertAndSend("/user/" + clientId + "/monitor", getOps());
}

我尝试了很多映射组合,例如“/ user / monitor- {clientId}”,“/ user / monitor”(删除clientId),完全没有成功。

预期的映射值是什么,所以这个被调用?

谢谢!

1 个答案:

答案 0 :(得分:11)

由于客户订阅了" / user / monitor"队列,服务器@SubscribeMapping注释必须是" / user / monitor"而不是" / user / monitor {something}"。

服务器可以根据您的身份验证方案了解客户端是什么。如果您使用sockjs websocket,您可以使用HTTP身份验证,从而利用Spring Security,并添加一个" Principal"函数的参数,用于保存用户信息:

@SubscribeMapping("/monitor")
public void init(Principal p) {
    String user = p.getName();
    messagingTemplate.convertAndSendToUser(user, "/monitor", getOps());
}

如果您不使用http身份验证,您可以向服务器发送用户信息,例如添加可以使用SimpMessageHeaderAccessor从服务器访问的自定义STOMP标头:

@SubscribeMapping("/monitor")
public void init(SimpMessageHeaderAccessor accessor) {
    String user = accessor.getFirstNativeHeader("userid");
    messagingTemplate.convertAndSendToUser(user, "/monitor", getOps());
}

另一种方法是订阅包含用户信息的不同队列名称(这可能是您的提议)。客户端必须使用类似于以下的代码:

stompClient.subscribe('/topic/byUser/'+userId, function(msg) {
    console.log(msg);    
});

以便服务器可以这样访问它:

@SubscribeMapping("/byUser/{userId}")
public void init(@DestinationVariable String userId) {
    messagingTemplate.convertAndSendToUser(userId, "/monitor", getOps());
}

但在这种情况下请记住,该队列是公共的,因此如果其他客户端知道其他客户端名称,则其他客户端可以访问这些消息。