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

时间:2019-03-07 20:50:42

标签: spring-boot spring-mvc websocket stomp

澄清:

由于@JustinBertram的评论,我意识到这个问题没有道理。

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

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

STOMP协议的文档对我来说并不清楚,我感到困惑。请参阅以下参考:

the specification

  

踩踏经纪人可能支持选择器标头,使您可以   在邮件标头上指定一个SQL 92选择器,该选择器用作   过滤基于内容的路由。

this article

  

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

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

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


我正在Spring Boot中实现一个后端。为了与前端进行双向通信,我在Websocket上使用了stomp。

我关注了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,但是我不知道如何在标题中设置选择器属性:

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

MessageSendingOperations<String> messagingTemplate;

messagingTemplate.convertAndSend(destination, quote);

我真的很感谢您的帮助,我已经阅读了许多文章和文档,但是没有找到关于此问题的解决方案。

2 个答案:

答案 0 :(得分:2)

好吧,可以将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 ==是Spring的Spel语法。

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

答案 1 :(得分:1)

latest version of the STOMP specification不包含有关选择器及其语法的任何特定声明,因为这实际上取决于中间件在此处支持的实现。规范现在说明:

  

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

像ActiveMQ 5.x和ActiveMQ Artemis这样的经纪人都支持selector STOMP标头,并且选择器的语法和行为基于JMS选择器。

JMS中的

选择器用于在消费时选择消息,并且由消费方客户端配置。发送消息时无法设置选择器。

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

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