Как ждать подписки?
У меня есть следующий код js:
stompClient.subscribe('/topic/clients', function (calResult) {
updateClientsTable(JSON.parse(calResult.body));
});
$.get("/clients", null);
и следующий код сервера (последняя строка вызывает его):
@GetMapping(value = {"/clients"})
@ResponseBody
public void loadClients() {
brokerMessagingTemplate.convertAndSend("/topic/clients", clientService.getClientList());
}
Когда-то front-end пропускает результат $.get("/clients", null);
Как я понимаю, проблема: в момент получения результата на лицевой стороне подписки не происходит.
если поставить $.get("/clients", null);
ниже в коде - все работает нормально.
Можете ли вы объяснить, как ждать подписки?
Ответы
Ответ 1
Как уже упоминалось @light_303, смешивание HTTP-запросов с механизмом уведомления не очень хорошо. Вы можете зарегистрировать момент, когда клиент подключается (запрос GET на /clients
), но вы не можете зарегистрироваться, когда он отключается.
Вы должны думать одним из следующих способов. Когда пользователь подписывается на /topic/clients
:
- Вы индивидуально отправляете ему ответ со всем списком клиентов, а затем только нажимаете обновления.
- Вы индивидуально отправляете ему текущее время сервера или какой-то идентификатор, а затем только обновляете обновления. Пользователь использует заданное время /ID в запросе GET для
/clients
и получает полный список клиентов в этот момент. Этот параметр может быть хорошим в ситуации, когда у вас есть инкрементные обновления (то есть добавление новых элементов в список), и в противном случае это не так хорошо.
Отметьте этот вопрос: Отправка сообщения конкретному пользователю в Spring Websocket.
Это на самом деле смешно, как Spring может усложнить ситуацию. Я рекомендую вам посмотреть другие фреймворки для веб-общения в реальном времени, такие как Vert.x или Netty и язык программирования Go Go. Используйте WebSockets или SockJS вместо STOMP. Все эти технологии могут дать вам более гибкое и эффективное решение. Кроме того, проверьте Centrifugo проект, возможно, это относится к вашей задаче.
Ответ 2
Я думаю, что было бы разумнее не смешивать запросы REST с этим шаблоном обмена сообщениями.
Рассматривали ли вы отправку команды "updateClients" через SockJS в канал "/apps/updateClients", который отвечает на канал "/topic/clients"?
Ответ 3
Вы можете использовать аннотацию @SubscribeMapping
от spring-messaging
.
Если у вас spring-messaging
настроено, как описано здесь и здесь, серверный код может выглядеть следующим образом:
@Controller
public class MessagingController {
@SubscribeMapping("/clients")
public List<Client> loadClients() {
return clientService.getClientList();
}
}
Таким образом, вам не нужно вызывать $.get("/clients", null);
, потому что обработчик сообщения JS получает результат loadClients()
call сразу после того, как происходит подписка. Код JS будет выглядеть так:
stompClient.subscribe('/topic/clients', function (calResult) {
updateClientsTable(JSON.parse(calResult.body));
});