首页 > 解决方案 > 如何在 Spring Boot 的 websocket 主题中使用选择器发送消息

问题描述

澄清:

感谢@JustinBertram 的评论,我意识到这个问题没有意义。

STOMP 协议本身不支持选择器,您必须使用实现它的代理,例如 ActiveMQ。STOMP 支持代理可以使用的标头,用于通过选择器过滤消息。

就我而言,我没有使用任何代理,只是前端使用 Angular + Stomp + SocksJS,后端使用 Spring Boot,所以我不能使用选择器。

STOMP 协议的文档并没有让我明白这一点,我很困惑。请参阅这些参考资料:

规格

Stomp 代理可能支持选择器标头,它允许您在消息标头上指定 SQL 92 选择器,作为基于内容的路由的过滤器。

这篇文章

subscribe() 方法采用可选的 headers 参数来指定订阅目标时的附加标头:

var headers = {ack: 'client', 'selector': "location = 'Europe'"};
client.subscribe("/queue/test", message_callback, headers);

客户端指定它将处理消息确认,并且有兴趣仅接收与选择器位置 = 'Europe' 匹配的消息。


我在 Spring Boot 中实现了一个后端。对于与前端的双向通信,我使用 stomp over websockets。

我遵循了这个 Spring Boot + Angular 示例

它可以工作,但我的一个要求是后端必须发送带有选择器的消息,以便前端订阅一个主题并且只接收过滤后的数据,以避免实时数据的性能问题。

IE{ 'selector': "location = 'Europe'" }

为此,我试图让后端使用选择器发送消息,但我无法让它工作。

我已经按照这篇文章用选择器实现了前端并且它工作正常,问题只是后端

我尝试使用@SendTo注释,但根据文章似乎没有任何参数:

@MessageMapping("/hello")
@SendTo("/topic/greetings")
public Greeting greeting(HelloMessage message) throws Exception {
    Thread.sleep(1000);
    return new Greeting("Hello, " + HtmlUtils.htmlEscape(message.getName()) + "!");
}

我也试过了MessagingTemplate,但我不知道如何在标题中设置选择器属性:

http://assets.spring.io/wp/WebSocketBlogPost.html

MessageSendingOperations<String> messagingTemplate;

messagingTemplate.convertAndSend(destination, quote);

我真的很感谢任何帮助,我已经阅读了很多文章和文档,但我没有找到任何关于这个解决方案的特别讨论。

标签: spring-bootspring-mvcwebsocketstomp

解决方案


好吧,可以将 JMS 的选择器与 Spring (Boot) Websocket 和 STOMP 客户端一起使用。我找到了一种本土的方式。

关键是选择器应用于org.springframework.messaging.Message实例它使用 Spring 的 Spel语言来应用条件(它不是 JMS SQL-like)。

因此,使用默认的 SimpMessagingTemplate,您可以在后端发送标头变量,如下所示:

this.messagingTemplate.convertAndSend(
    "/topic/something", //your destination
    payload, //any kind of payload (body)
    Map.of("id", 1) //header with key/value
);

在前端,要输入将由 评估的选择器org.springframework.messaging.simp.broker.DefaultSubscriptionRegistry.filterSubscriptions,您必须将 Stomp/WebSockets 标头声明为:

{"selector": "headers['nativeHeaders']['id'][0] == '999'"}

是的,这很可怕,但它有效。

默认情况下Message,标头在一个名为“nativeHeaders”GenericMessage的新键中处理。是 Spring的Spel 语法。['key'],[0] and ==

请继续在后端过滤您的消息,而不是在前端!


推荐阅读