8

我正在Spring 4中使用内置Message BrokerSTOMP over WebSocket开发实时通知系统。

我希望能够根据他的用户名向特定用户发送消息。为了达到这个目的,我使用的convertAndSendToUser是class的方法org.springframework.messaging.simp.SimpMessagingTemplate,如下:

private final MessagingTemplate messagingTemplate;

@Autowired
public LRTStatusListener(SimpMessagingTemplate messagingTemplate) {
    this.messagingTemplate = messagingTemplate;
}


@Scheduled(fixedDelay=5000)
public void sendMessages(Principal principal)
    messagingTemplate
        .convertAndSendToUser(principal.getName(), "/horray", "Horray, " + principal.getName() + "!");
}

作为配置:

@Configuration
@EnableScheduling
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/notifications").withSockJS();
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.enableSimpleBroker("/topic", "/queue", "/user");
    }

}

客户端(通过JavaScript),我应该通过指定用户名来订阅频道(根据另一个非常相似的问题:在 Spring Websocket 上向特定用户发送消息)。

stompClient.subscribe('/user/' + username + '/horray, ...) 

最后一点听起来很奇怪......

假设我在我的 webapp 上登录为w.white,通过订阅:

stompClient.subscribe('/user/w.white/horray, ...)

...我将能够看到发送到w.white的消息,这太棒了...但是订阅:

stompClient.subscribe('/user/j.pinkman/horray, ...)

...我也将能够看到发送到j.pinkman的消息,尽管我目前登录为w.white

这是一种克服这个问题的方法吗?


更新

下面是关于通过 WebSocket 进行连接的日志:

Opening Web Socket... 
Web Socket Opened... 
>>> CONNECT
accept-version:1.1,1.0
heart-beat:10000,10000

<<< CONNECTED
user-name:w.white
heart-beat:0,0
version:1.1

connected to server undefined
Connected: CONNECTED
version:1.1
heart-beat:0,0
user-name:w.white

>>> SUBSCRIBE
id:sub-0
destination:/topic/lrt

>>> SUBSCRIBE
id:sub-1
destination:/user/lrt
4

2 回答 2

25

我找到了解决方案。

首先,重要的是要知道该/user通道已经由Spring STOMP管理,顺便说一句,不需要注册。

所以:

@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
    registry.enableSimpleBroker("/topic", "/queue");
}

然后,我将目标频道设置为/queue/horray

@Scheduled(fixedDelay=5000)
public void sendMessages(Principal principal)
    messagingTemplate
        .convertAndSendToUser(principal.getName(), "/queue/horray", "Horray, " + principal.getName() + "!");
}

最后,在客户端:

stompClient.subscribe('/user/queue/horray', '...');

现在,它工作正常!Principal根据安全上下文获取的信息,消息仅发送给指定的收件人。

于 2014-09-03T15:07:42.167 回答
7

由于我的应用程序上的用户未经过身份验证,我只是使用会话 ID 来区分各种主题

在服务器上:

template.convertAndSend("/topic/warnings/" + sessionId, ...)

客户端非常简单

stompClient.subscribe('/topic/warnings/${pageContext.session.id}', ...

也许不是最干净的方式,但它有效,并且没有身份验证我无法使用 /user 频道

于 2015-06-22T21:30:59.377 回答