Действительно ли Spring @SubscribeMapping подписывает клиента на какую-то тему?
Я использую Spring Websocket с STOMP, Simple Message Broker. В моем@Controller
Я использую метод уровня@SubscribeMapping
, который должен подписать клиента на тему, чтобы клиент мог получать сообщения по этой теме впоследствии. Допустим, клиент подписывается на тему«Чат»:
stompClient.subscribe('/app/chat', ...);
Как клиент подписался на«/ Приложение / чат", вместо«/ Тема / чат»эта подписка будет идти к методу, который отображается с помощью@SubscribeMapping
:
@SubscribeMapping("/chat")
public List getChatInit() {
return Chat.getUsers();
}
Вот то, что весна исх. говорит:
По умолчанию возвращаемое значение из метода @SubscribeMapping отправляется в виде сообщения непосредственно обратно подключенному клиенту и не проходит через посредник. Это полезно для реализации взаимодействия между запросом и ответом; например, для извлечения данных приложения, когда пользовательский интерфейс приложения инициализируется.
Хорошо, это было то, что я хотел бы, но просточастично!! Отправка некоторых init-данных после подписки, хорошо. Но что насчетподписавшийся? Мне кажется, что то, что произошло здесь, это простозапрос-ответ, как услуга. Подписка только что потребляется. Пожалуйста, уточните мне, если это так.
Подписывался ли клиент на что-то, где, если брокер не вовлечен в это?Если позже я захочу отправить какое-нибудь сообщение подписчикам чата, получит ли его клиент? Это не так.Кто реализует подписки на самом деле? Маклер? Или кто-то еще?Если здесь клиент не подписан ни на что, мне интересно, почему мы называем это «подписаться»; потому что клиент получает только одно сообщение, а не будущие сообщения.
РЕДАКТИРОВАТЬ:
Чтобы убедиться, что подписка была реализована, я попробовал следующее:
Серверный:
Конфигурация:
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/hello").withSockJS();
}
}
контроллер:
@Controller
public class GreetingController {
@MessageMapping("/hello")
@SendTo("/topic/greetings")
public Greeting greeting(HelloMessage message) throws Exception {
System.out.println("inside greeting");
return new Greeting("Hello, " + message.getName() + "!");
}
@SubscribeMapping("/topic/greetings")
public Greeting try1() {
System.out.println("inside TRY 1");
return new Greeting("Hello, " + "TRY 1" + "!");
}
}
Сторона клиента:
...
stompClient.subscribe('/topic/greetings', function(greeting){
console.log('RECEIVED !!!');
});
stompClient.send("/app/hello", {}, JSON.stringify({ 'name': name }));
...
То, что я хотел бы случиться:
Когда клиент подписывается на/topic/greetings
', методtry1
выполнен.Когда клиент отправляет сообщение в/app/hello
', он должен получить приветственное сообщение, которое будет@SendTo
'/topic/greetings
».Результаты:
Если клиент подписывается на/topic/greetings
, методtry1
НЕВОЗМОЖНО поймать его.
Когда клиент отправляет сообщение в/app/hello
»,greeting
Метод был выполнен, и клиент получил приветственное сообщение. Таким образом, мы поняли, что он был подписан на/topic/greetings
'правильно.
Но помните 1. не удалось. После некоторой попытки это стало возможным, когда клиент подписался на'/app/topic/greetings'
то есть с префиксом/app
(Это понятно по конфигурации).
Сейчас 1. работает, однако на этот раз 2. не удалось: когда клиент отправляет сообщение «/app/hello
', да,greeting
метод был выполнен, но клиент НЕ получил сообщение приветствия. (Потому что, вероятно, теперь клиент был подписан на тему с префиксом '/app
', который был нежелательным.)
Итак, я получил 1 или 2 того, что хотел бы, но не эти 2 вместе.
Как мне добиться этого с этой структурой (правильная настройка путей сопоставления)?