ПОЯСНЕНИЯ :

Благодаря комментарию @JustinBertram я понял, что этот вопрос не имеет смысла.

Протокол STOMP сам по себе не поддерживает селекторы, вам нужно использовать таких брокеров, как ActiveMQ, которые его реализуют . STOMP поддерживает заголовки, которые могут использоваться брокерами для фильтрации сообщений по селекторам.

В моем случае я не использую какого-либо брокера, просто интерфейс с Angular + Stomp + SockJS и сервер с Spring Boot, поэтому я не могу использовать селекторы.

Документация по протоколу STOMP не дает мне этого понять, и я запутался. Смотрите эти ссылки:

спецификация:

Брокеры Stomp могут поддерживать заголовок селектора, который позволяет указывать селектор SQL 92 в заголовках сообщений, который действует как фильтр для маршрутизации на основе содержимого.

эта статья:

Метод subscribe () принимает необязательный аргумент headers для указания дополнительных заголовков при подписке на пункт назначения:

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

Клиент указывает, что он будет обрабатывать подтверждение сообщения и заинтересован в получении только сообщений, соответствующих селектору location = 'Europe'.


Я реализую бэкэнд в Spring Boot. Для двусторонней связи с внешним интерфейсом я использую stomp поверх websockets.

Я следовал этому примеру Spring Boot + Angular

Это работает, но одно из моих требований заключается в том, что сервер должен отправлять сообщения с селекторами, чтобы веб-интерфейс подписывался на тему и получал только отфильтрованные данные , чтобы избежать проблем с производительностью в режиме реального времени.

То есть { '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);

Я действительно ценю любую помощь, я прочитал много статей и документов, но я не нахожу ничего, что конкретно говорит об этом с решением.

0
Daniel Perales 7 Мар 2019 в 23:50

2 ответа

Лучший ответ

последняя версия спецификации STOMP не содержит каких-либо конкретных утверждений о селекторах и их синтаксисе, потому что это зависит от реализации брокера относительно того, что здесь поддерживается. Спецификация теперь просто заявляет:

Серверы STOMP МОГУТ поддерживать дополнительные серверные заголовки для настройки семантики доставки подписки. Обратитесь к документации вашего сервера для деталей.

Брокеры, такие как ActiveMQ 5.x и ActiveMQ Artemis, поддерживают заголовок STOMP selector, а синтаксис и поведение селектора основаны на селекторах JMS.

Селекторы в JMS предназначены для выбора сообщений при использовании и настраиваются клиентом-потребителем. Вы не можете установить селектор при отправке сообщения.

Селекторы JMS выбирают сообщения на основе заголовков или свойств сообщения, хотя некоторые реализации выходят за рамки этого и позволяют выбирать на основе содержимого самого сообщения. Поэтому, если вы хотите иметь селектор location = 'Europe' для получателя, вам следует установить заголовок сообщения при его отправке с именем location и значением Europe.

Метод convertAndSend перегружен и предоставляет несколько способов установить заголовок:

1
Justin Bertram 9 Мар 2019 в 15:34

Что ж, можно использовать селекторы JMS с Spring (Boot) 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'"}

Да, это ужасно, но это работает.

Поскольку по умолчанию Message - GenericMessage, заголовки обрабатываются в новом ключе с именем «nativeHeaders» . ['key'],[0] and == - синтаксис Spring Spel.

Идите вперед и отфильтруйте свои сообщения на сервере, а не на интерфейсе, пожалуйста!

1
Rodrigo Pereira Fraga 21 Фев 2020 в 05:16