Spring中使用带有用户目标的Stomp @SubscribeMapping("/user/...")无法正常工作。

16

我需要对用户的目标订阅进行反应。

示例:

一个用户订阅了/user/messages,因为他想接收所有进入的消息。现在我想查找任何在他离线期间创建的面向该用户的消息,并将它们发送给该用户。

可用代码:

客户端代码:

stompClient.subscribe('/user/messages', function(msg){
    alert(msg.body);
});

服务器代码:

template.convertAndSendToUser(p.getName(), "/messages", "message content");

我需要什么:

似乎无法在服务器端捕获用户的目的地订阅,即:

@SubscribeMapping("/user/messages")
public void test(Principal p) { 
    sendMessagesThatWereReceivedWhileUserWasOffline();
}

我尝试了什么:

@SubscribeMapping("/messages")
public void test(Principal p) { ... }

如果客户端订阅了/app/messages它将有效,但不会为/user/messages调用。

我的配置:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/stomp").withSockJS();
    }

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

    @Override
    public boolean configureMessageConverters(List<MessageConverter> messageConverters) {
        return true;
    }

    // all other methods left empty
}

使用Spring 4.1。


我无法想象这是不可能的。我错过了什么/做错了什么?

谢谢:)

1个回答

20

将用户前缀定义为应用程序前缀,然后您将能够在控制器中映射订阅。配置:

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

控制器:

@SubscribeMapping("/messages")
public void test(Principal p) { 
    sendMessagesThatWereReceivedWhileUserWasOffline();
}

谢谢!这个配置会“破坏”什么或改变默认行为吗?我只是想知道为什么这不是默认设置。 - Benjamin M
这个配置不会破坏任何东西,以“/user”开头的消息将被发送到用户目标处理程序和您的控制器。 - Sergi Almar
有没有不使用 Principal 的解决方案? - Pepster
Pepster,你可以提出一个单独的问题。你可以使用@Headers从消息头中获取数据,但这可能不是你想要问的。 - rwitzel
非常好的答案,谢谢。但是我遇到了以下错误?有什么建议吗?org.springframework.messaging.simp.annotation.support.MissingSessionUserException: 消息中没有"user"头信息。 - Robert Leggett
嗨 @SergiAlmar,我正在实现帖子和评论模块,我应该创建多少个订阅通道例如addPost、updatePost、addComment、updateComment。我是否应该为它们创建单独的订阅通道?这不是针对用户,对所有用户可见。 - Shantaram Tupe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接