Websocket отслеживает соединения в Spring

Сегодня я искал пару часов для реализации или учебника о том, как отслеживать подключения к веб-сокетам в Spring.

Я сделал (очень хороший) учебник Spring о веб-сокетах и ​​STOMP. ссылка здесь

Итак, какова моя настройка, у меня есть приложение Ionic Hybrid с бэкэндом Spring, и я хочу отправлять уведомление клиенту всякий раз, когда в бэкэнде возникает новое событие-уведомление. Весь этот код уже реализован и подключение работает, но сейчас нет возможности указать, куда должны идти уведомления.

По этому вопросу нет учебника или объяснения, которое следует структуре учебника Spring (по крайней мере, после 5 часов исследований), и я немного ошеломлен всей информацией о веб-сокетах и ​​​​безопасности в Интернете. (Я узнаю о веб-сокетах всего 2 дня)

Итак, для всего, что было до меня и будет после меня, я думаю, что может быть очень полезно иметь компактный и легкий ответ, следуя структуре, изложенной в Spring Tutorial.

Я нашел этот вопрос без ответа на StackOverflow о тех же проблемах, что и у меня, поэтому я уверен, что эти вопросы докажут свою ценность.

TL;DR

Как реализовать список в серверной части, который отслеживает соединения, на основе Учебное пособие по Spring WebSocket ?

Как отправить данные с клиента на бэкенд при установленном соединении? (например, идентификатор пользователя или токен)


person Sytham    schedule 02.08.2016    source источник
comment
Вы действительно нашли время, чтобы прочитать Справочное руководство?   -  person M. Deinum    schedule 02.08.2016
comment
Я так и сделал, и, как я уже сказал, все было ошеломляюще, поэтому я думаю, что простой и универсальный ответ может быть очень полезен для новых учеников, таких как я.   -  person Sytham    schedule 03.08.2016


Ответы (3)


Так что я понял это сам.

Мои уведомления имеют идентификатор получателя (идентификатор пользователя, которому необходимо отправлять уведомления)

Итак, я собираюсь отправить '/ws-user/'+id+'/greetings', где id — это пользователь, вошедший в систему.

На стороне клиента этого довольно легко добиться.

 var stompClient = null;

  // init
  function init() {
          /**
           * Note that you need to specify your ip somewhere globally
           **/
      var socket = new SockJS('http://127.0.0.1:9080/ws-notification');
      stompClient = Stomp.over(socket);
      stompClient.connect({}, function(frame) {
          console.log('Connected: ' + frame);
          /**
           * This is where I get the id of the logged in user
           **/
          barService.currentBarAccountStore.getValue().then(function (barAccount) {
              subscribeWithId(stompClient,barAccount.user.id);
          });
      });
  }

          /**
           * subscribe at the url with the userid
           **/
  function subscribeWithId(stompClient,id){
      stompClient.subscribe('/ws-user/'+id+'/greetings', function(){
          showNotify();
      });
  }
          /**
           * Broadcast over the rootscope to update the angular view 
           **/
  function showNotify(){
      $rootScope.$broadcast('new-notification');
  }

  function disconnect() {
      if (stompClient != null) {
          stompClient.disconnect();
      }
      // setConnected(false);
      console.log("Disconnected");
  }

Затем мы добавляем «setUserDestinationPrefix» в MessageBrokerRegistry в классе WebSocketConfig.java:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    private final static String userDestinationPrefix = "/ws-user/";

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config){
        config.enableSimpleBroker("/ws-topic","/ws-user");
        config.setApplicationDestinationPrefixes("/ws-app");
        config.setUserDestinationPrefix(userDestinationPrefix);
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/ws-notification").setAllowedOrigins("*").withSockJS();
    }
}

Обратите внимание, что я использую внутренние вызовы RestTemplate для доступа к моему методу контроллера, который отправляет уведомление подписанному клиенту. Это делается классом потребителя событий (попросите показать код, он просто запускает функцию контроллера, можно было бы сделать по-другому)

@RequestMapping(value = "/test-notification", method = RequestMethod.POST)
public void testNotification(@RequestBody String recipientId) throws InterruptedException {
    this.template.convertAndSendToUser(recipientId,"/greetings", new Notify("ALERT: There is a new notification for you!"));
}

Пожалуйста, просмотрите мой код и предупредите меня, если вы обнаружите какие-либо проблемы и/или проблемы с безопасностью.

person Sytham    schedule 05.08.2016
comment
Можете ли вы поделиться кодом? как узнать, какой сокет использовать для отправки сообщения клиенту? - person N Jay; 20.02.2018
comment
@Sytham Можете ли вы поделиться кодом, пожалуйста? Я застрял при отправке сообщения клиенту. Спасибо. - person Toluwalemi; 03.02.2021

Для пользовательской доставки в веб-сокете вы можете использовать объекты Principle с безопасностью spring. Вот хороший пример реализации:

https://github.com/rstoyanchev/spring-websocket-portfolio

Безопасность Spring проверит SAME ORIGIN, и с вашего клиента вы можете отправить заголовок stomp с указанным используемым идентификатором.

Надеюсь, это поможет вам.

person Aditya    schedule 03.08.2016

Взгляните на этот ответ: Как получить все активные сеансы в Spring 5 WebSocket API?

Вы можете получить подключенных пользователей с помощью SimpUserRegistry API Spring.

person Florian Lopes    schedule 18.01.2019