如何在 Spring 引导中的 websocket 主题中使用选择器发送消息



澄清:

多亏@JustinBertram评论,我意识到这个问题没有意义。

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

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

STOMP协议的文档没有向我说明这一点,我感到困惑。请参阅以下参考资料:

规格:

踩踏经纪人可能支持选择器标头,它允许您 在消息头上指定一个 SQL 92 选择器,该选择器充当 筛选基于内容的路由。

本文:

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

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

客户端指定它将处理消息确认 并且只对接收与选择器匹配的消息感兴趣 位置 ="欧洲"。


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

我遵循了这个弹簧启动+角度示例

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

{ '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);

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

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

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

因此,使用默认的 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'"}

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

由于默认MessageGenericMessage,因此标头在一个名为"nativeHeaders">的新键中处理。['key'],[0] and ==是春天的斯佩尔罪恶。

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

最新版本的 STOMP 规范不包含任何关于选择器及其语法的特定语句,因为这里支持的内容实际上取决于代理实现。规范现在只声明:

STOMP 服务器可能支持其他特定于服务器的标头,以自定义订阅的传递语义。有关详细信息,请参阅服务器的文档。

像ActiveMQ5.x和ActiveMQ Artemis这样的代理支持selectorSTOMP标头,选择器的语法和行为基于JMS选择器。

JMS 中的选择器用于选择使用时的消息,由使用客户端配置。发送消息时无法设置选择器。

JMS 选择器根据消息的标头或属性选择消息,尽管某些实现超出了此范围,并允许根据消息本身的内容进行选择。因此,如果要在使用者上location = 'Europe'选择器,则应在发送消息时以名称location和值Europe在消息上设置标头。

convertAndSend方法已重载,并提供了几种设置标头的方法:

  • 将键/值对的映射传递给convertAndSend方法。
  • 实现MessagePostProcessor并将其传递给convertAndSend方法。在后处理器内部,您可以调用javax.jms.Message#setStringProperty()方法。

最新更新