spring-boot - 如何在 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);
我真的很感谢任何帮助,我已经阅读了很多文章和文档,但我没有找到任何关于这个解决方案的特别讨论。
解决方案
好吧,可以将 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 ==
请继续在后端过滤您的消息,而不是在前端!
推荐阅读
- flyway - 自动创建数据库
- java - 您如何更新文档中的文档?MongoDB Java
- reactjs - 如何在将道具值传递给另一个组件时避免箭头功能?
- php - 如何从 Codeigniter 3.1.9 的 url 中删除 index.php
- node.js - Node.js 和 amcharts4 - 使用 TypeSript 或 ES6 导入错误“意外令牌导出”
- c++ - 更简洁的方式来声明高维向量
- java - 使用 java cv 时在 android studio 上出现构建错误
- reactjs - 在我的反应原生项目中显示没有互联网连接
- angular - Angular 5:新数据与旧数据合并
- r - 警告:`pkgname` 既不是文件也不是目录,跳过