问题 使用用户目标的Spring Stomp @SubscribeMapping(“/ user / ...”)不起作用


我需要对用户目标订阅做出反应。

例:

用户订阅 /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。


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

谢谢 :)


10891
2017-09-19 06:55


起源



答案:


将用户前缀也定义为应用程序前缀,然后您就可以在控制器中映射订阅。组态:

@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();
}

10
2017-09-19 10:49



谢谢 !这个配置是“破坏”任何东西还是改变默认行为?我只是想知道为什么这不是默认设置 - Benjamin M
此配置不会破坏任何内容,以/ user开头的消息将传递给用户目标处理程序和控制器 - Sergi Almar
是否还有一个没有使用Principal的解决方案? - Pepster
Pepster,您可能会在另一个问题中提出问题。你可以使用@Headers从消息的标题中获取数据..但这可能不是你想要问的。 - rwitzel
很好的答案谢谢,但是我收到以下错误?有什么建议么? org.springframework.messaging.simp.annotation.support.MissingSessionUserException:消息中没有“user”标头 - Robert Leggett


答案:


将用户前缀也定义为应用程序前缀,然后您就可以在控制器中映射订阅。组态:

@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();
}

10
2017-09-19 10:49



谢谢 !这个配置是“破坏”任何东西还是改变默认行为?我只是想知道为什么这不是默认设置 - Benjamin M
此配置不会破坏任何内容,以/ user开头的消息将传递给用户目标处理程序和控制器 - Sergi Almar
是否还有一个没有使用Principal的解决方案? - Pepster
Pepster,您可能会在另一个问题中提出问题。你可以使用@Headers从消息的标题中获取数据..但这可能不是你想要问的。 - rwitzel
很好的答案谢谢,但是我收到以下错误?有什么建议么? org.springframework.messaging.simp.annotation.support.MissingSessionUserException:消息中没有“user”标头 - Robert Leggett