如何在 Spring 引导中使用 websocket 主题中的选择器发送消息
How to send messages with selectors in websocket topic in Spring Boot
澄清:
感谢@JustinBertram 的评论,我意识到这个问题没有意义。
STOMP 协议本身不支持选择器,您必须使用实现它的代理,例如 ActiveMQ。 STOMP 支持 headers,代理可以使用它们来通过选择器过滤消息。
就我而言,我没有使用任何代理,只是前端使用 Angular + Stomp + SocksJS,后端使用 Spring Boot,所以我不能使用选择器。
STOMP 协议的文档没有让我清楚这一点,我感到很困惑。请参阅这些参考资料:
Stomp brokers may support the selector header which allows you to
specify an SQL 92 selector on the message headers which acts as a
filter for content based routing.
The subscribe() method takes an optional headers argument to specify
additional headers when subscribing to a destination:
var headers = {ack: 'client', 'selector': "location = 'Europe'"};
client.subscribe("/queue/test", message_callback, headers);
The client specifies that it will handle the message acknowledgement
and is interested to receive only messages matching the selector
location = 'Europe'.
我正在 Spring Boot 中实现一个后端。对于 two-way 与前端的通信,我使用 stomp over websockets。
我关注了this Spring Boot + Angular example
可以,但是我的一个要求是后端必须发送带有选择器的消息,以便前端订阅一个主题并且只接收过滤后的数据,以避免实时数据的性能问题。
即{ 'selector': "location = 'Europe'" }
为此,我试图让后端发送带有选择器的消息,但我做不到。
我已经按照 this article 实现了带有选择器的前端并且它工作正常,只有后端有问题。
我尝试使用 @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
,但我不知道如何在 header:
中设置选择器属性
http://assets.spring.io/wp/WebSocketBlogPost.html
MessageSendingOperations<String> messagingTemplate;
messagingTemplate.convertAndSend(destination, quote);
非常感谢任何帮助,我已经阅读了很多文章和文档,但我没有找到任何特别讨论此问题的解决方案。
latest version of the STOMP specification 不包含任何关于 selector 及其语法的特定声明,因为关于此处支持的内容,这实际上取决于代理实施。规范现在只声明:
STOMP servers MAY support additional server specific headers to customize the delivery semantics of the subscription. Consult your server's documentation for details.
ActiveMQ 5.x 和 ActiveMQ Artemis 等代理支持 selector
STOMP header 并且 selector 的语法和行为基于 JMS select或
JMS 中的选择器用于 selecting 消费消息,由消费客户端配置。发送消息时不能设置selector。
JMS select或 select 基于 header 或消息属性的消息,尽管一些实现超出了这一点并允许 selecting 基于消息本身的内容。因此,如果您想在消费者上使用 select 或 location = 'Europe'
,那么您应该在消息以名称 location
和值发送时在消息上设置 header共 Europe
.
convertAndSend
方法被重载并提供了两种设置 header:
的方法
- 将 key/value 对的映射传递给
convertAndSend
方法。
- 实施
MessagePostProcessor
and pass that to the convertAndSend
method. Inside your post-processor you can invoke the javax.jms.Message#setStringProperty()
方法。
嗯,可以将 JMS 的选择器与 Spring(引导)Websocket 和 STOMP 客户端一起使用。我找到了原生方式。
关键是选择器应用于org.springframework.messaging.Message
实例,它使用Spring的Spel 应用条件的语言(不是 JMS SQL-like)。
所以使用默认的 SimpMessagingTemplate,在后端你可以像这样发送 header 个变量:
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 header 声明为:
{"selector": "headers['nativeHeaders']['id'][0] == '999'"}
是的,这很糟糕,但它确实有效。
由于默认的 Message
是 GenericMessage
,header 将在名为 "nativeHeaders" 的新密钥中进行处理。
['key'],[0] and ==
是 Spring 的 Spel 语法。
请继续在后端过滤您的消息,而不是在前端!
澄清:
感谢@JustinBertram 的评论,我意识到这个问题没有意义。
STOMP 协议本身不支持选择器,您必须使用实现它的代理,例如 ActiveMQ。 STOMP 支持 headers,代理可以使用它们来通过选择器过滤消息。
就我而言,我没有使用任何代理,只是前端使用 Angular + Stomp + SocksJS,后端使用 Spring Boot,所以我不能使用选择器。
STOMP 协议的文档没有让我清楚这一点,我感到很困惑。请参阅这些参考资料:
Stomp brokers may support the selector header which allows you to specify an SQL 92 selector on the message headers which acts as a filter for content based routing.
The subscribe() method takes an optional headers argument to specify additional headers when subscribing to a destination:
var headers = {ack: 'client', 'selector': "location = 'Europe'"}; client.subscribe("/queue/test", message_callback, headers);
The client specifies that it will handle the message acknowledgement and is interested to receive only messages matching the selector location = 'Europe'.
我正在 Spring Boot 中实现一个后端。对于 two-way 与前端的通信,我使用 stomp over websockets。
我关注了this Spring Boot + Angular example
可以,但是我的一个要求是后端必须发送带有选择器的消息,以便前端订阅一个主题并且只接收过滤后的数据,以避免实时数据的性能问题。
即{ 'selector': "location = 'Europe'" }
为此,我试图让后端发送带有选择器的消息,但我做不到。
我已经按照 this article 实现了带有选择器的前端并且它工作正常,只有后端有问题。
我尝试使用 @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
,但我不知道如何在 header:
http://assets.spring.io/wp/WebSocketBlogPost.html
MessageSendingOperations<String> messagingTemplate;
messagingTemplate.convertAndSend(destination, quote);
非常感谢任何帮助,我已经阅读了很多文章和文档,但我没有找到任何特别讨论此问题的解决方案。
latest version of the STOMP specification 不包含任何关于 selector 及其语法的特定声明,因为关于此处支持的内容,这实际上取决于代理实施。规范现在只声明:
STOMP servers MAY support additional server specific headers to customize the delivery semantics of the subscription. Consult your server's documentation for details.
ActiveMQ 5.x 和 ActiveMQ Artemis 等代理支持 selector
STOMP header 并且 selector 的语法和行为基于 JMS select或
JMS 中的选择器用于 selecting 消费消息,由消费客户端配置。发送消息时不能设置selector。
JMS select或 select 基于 header 或消息属性的消息,尽管一些实现超出了这一点并允许 selecting 基于消息本身的内容。因此,如果您想在消费者上使用 select 或 location = 'Europe'
,那么您应该在消息以名称 location
和值发送时在消息上设置 header共 Europe
.
convertAndSend
方法被重载并提供了两种设置 header:
- 将 key/value 对的映射传递给
convertAndSend
方法。 - 实施
MessagePostProcessor
and pass that to theconvertAndSend
method. Inside your post-processor you can invoke thejavax.jms.Message#setStringProperty()
方法。
嗯,可以将 JMS 的选择器与 Spring(引导)Websocket 和 STOMP 客户端一起使用。我找到了原生方式。
关键是选择器应用于org.springframework.messaging.Message
实例,它使用Spring的Spel 应用条件的语言(不是 JMS SQL-like)。
所以使用默认的 SimpMessagingTemplate,在后端你可以像这样发送 header 个变量:
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 header 声明为:
{"selector": "headers['nativeHeaders']['id'][0] == '999'"}
是的,这很糟糕,但它确实有效。
由于默认的 Message
是 GenericMessage
,header 将在名为 "nativeHeaders" 的新密钥中进行处理。
['key'],[0] and ==
是 Spring 的 Spel 语法。
请继续在后端过滤您的消息,而不是在前端!