Я использую 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 вместе.
- Как достичь этого с помощью этой структуры (правильно настроив пути отображения)?