Как отправлять сообщения с селекторами в теме websocket в Spring Boot

ПОЯСНЕНИЕ:

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

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

В моем случае я не использую никакого брокера, только интерфейс с 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. Для двусторонней связи с интерфейсом я использую Stomp через веб-сокеты.

Я подписался на этот пример 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);

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

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Версия Java на основе версии загрузки
Версия Java на основе версии загрузки
Если вы зайдете на официальный сайт Spring Boot , там представлен start.spring.io , который упрощает создание проектов Spring Boot, как показано ниже.
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
0
0
1 522
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

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

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, а синтаксис и поведение селектора основаны на селекторах JMS.

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

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

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

  • Передайте карту пар ключ/значение методу convertAndSend.
  • Реализуйте MessagePostProcessor и передайте его методу convertAndSend. Внутри вашего постпроцессора вы можете вызвать метод javax.jms.Message#setStringProperty().

Спасибо, Джастин! Я использую топать через веб-сокет, а не JMS. Я думаю, что ваше объяснение метода sendAndConvert - это то, что я искал. Дайте мне попробовать, и я дам вам знать :-)

Dani P. 09.03.2019 01:38

Опс! Я все запутал, ваш комментарий имеет смысл.

Dani P. 09.03.2019 11:28

Я отредактировал сообщение, чтобы было ясно, что это было мое недоразумение. Спасибо!

Dani P. 09.03.2019 11:41

Что ж, можно использовать селекторы JMS с Spring (Boot) Websocket и клиентом STOMP. Нашел родной способ.

Ключевым моментом является то, что язык селектор применяется к экземпляру org.springframework.messaging.Message и он использует заклинание Spring применяют условие (это не похоже на 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, заголовки обрабатываются в новом ключе с именем "родные заголовки". ['key'],[0] and == - это синтаксис Spring Spel.

Пожалуйста, фильтруйте свои сообщения в бэкэнде, а не во внешнем интерфейсе!

Другие вопросы по теме