Я использую Spring Websocket с STOMP, Simple Message Broker.
В моем @Controller
я использую метод-уровень @SubscribeMapping
, который должен подписывать клиента на тему, чтобы потом клиент получал сообщения этой темы. Скажем, клиент подписывается на тему "чат" :
stompClient.subscribe('/app/chat', ...);
Когда клиент подписался на "/приложение/чат", вместо "/topic/chat" , эта подписка перейдет к методу, который отображается с использованием @SubscribeMapping
:
@SubscribeMapping("/chat")
public List getChatInit() {
return Chat.getUsers();
}
Вот что Spring ref. говорит:
По умолчанию отправляется возвращаемое значение из метода @SubscribeMapping как сообщение непосредственно обратно подключенному клиенту и не проходит через посредника. Это полезно для реализации запроса-ответа взаимодействие сообщений; например, для получения данных приложения, когда пользовательский интерфейс приложения инициализируется.
Хорошо, это то, что я хотел бы, но просто частично!! Отправка некоторых init-данных после подписки, ну. Но как насчет подписки? Мне кажется, что то, что произошло здесь, это просто запрос-ответ, как сервис. Подписка просто поглощена. Просьба уточнить, если это так.
- Подписывался ли клиент кому-то, где, если брокер не участвует в этом?
- Если позже я хочу отправить какое-то сообщение в "подписчики" чата, получит ли клиент его? Кажется, это не так.
- Кто понимает подписки на самом деле? Маклер? Или кто-то еще?
Если здесь клиент не подписывается ни на что, интересно, почему мы называем это "подпиской"; потому что клиент получает только одно сообщение, а не будущие сообщения.
EDIT:
Чтобы убедиться, что подписка реализована, я попробовал следующее:
Серверный:
Конфигурация:
@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
равен выполняется. - Когда клиент отправляет msg в '
/app/hello
', он должен получать приветствия msg, который будет@SendTo
'/topic/greetings
'.
Результаты:
-
Если клиент подписывается на
/topic/greetings
, методtry1
является UNABLE, чтобы его поймать. -
Когда клиент отправляет msg в '
/app/hello
', был выполнен методgreeting
, и клиент получил сообщение приветствия. Таким образом, мы поняли, что он был правильно подписан <<28 > . -
Но помните, что 1. не удалось. После некоторой попытки было возможно, когда клиент подписался на
'/app/topic/greetings'
, то есть с префиксом/app
(это понятно по конфигурации). -
Теперь работает 1., но на этот раз 2. не удалось: когда клиент отправляет сообщение msg в '
/app/hello
, да,greeting
метод был выполнен, но клиент НЕ получил сообщение приветствия, (Потому что, вероятно, теперь клиент был подписан на тему с префиксом "/app
", которая была нежелательной.)
Итак, у меня есть 1 или 2 из того, что я хотел бы, но не эти 2 вместе.
- Как достичь этого с помощью этой структуры (правильно настроив пути отображения)?