У меня возникла проблема, связанная с тем, что сообщение stomp, отправленное в пользовательское место назначения, не принимается клиентом. Позвольте мне объяснить:

В WebSocketMessageBrokerConfigurer:

public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/secured/topic", "/secured/user/queue");
config.setUserDestinationPrefix("/secured/user");
..

На моем клиенте stompjs (вошел под именем "admin"):

stompClient.subscribe('/secured/user/queue/notifications'
                        , function (output) {
                            console.log(output);
                        });

В журнале:

Processing SUBSCRIBE /secured/user/queue/notifications id=sub-0 session=d74f49b3-bb63-580f-b862-81647cc712b3

И код java для отправки сообщения:

simpMessagingTemplate.convertAndSendToUser(
      "admin", "/secured/user/queue/notifications", out);

В результате получается журнал:

Processing MESSAGE destination=/secured/user/queue/notifications-userd74f49b3-bb63-580f-b862-81647cc712b3 session=null payload={"from":"server","text":"hello","recipient":"admin","time":"13:29:10"}
      - 

Но в журнале консоли не выводится никакого сообщения.

Как вы можете видеть, sessionid одинаков на шаге подписки и отправки. Но я не понимаю, почему клиент не получает сообщение. Обратите внимание, что сообщения без назначения пользователя работают правильно.

Может ли кто-нибудь протянуть мне руку помощи?

Ответы (2)

Я заставил его работать, перепробовав множество вариантов, я только не уверен, почему он работает, но я не жалуюсь. Что я сделал:

В configureMessageBroker (WebSocketMessageBrokerConfigurer) (это действительно смущает меня, противоречит всем примерам, которые я читал):

config.enableSimpleBroker("/secured/topic", "/secured/queue", "/secured/user");

convertAndSendToUser (имя пользователя "/secured/user" + имя пользователя добавляется convertAndSendToUser):

simpMessagingTemplate.convertAndSendToUser(   "admin", "/queue/notifications", out);

и моя подписка на клиента (не очень рад добавлению имени пользователя здесь...):

stompClient.subscribe("/secured/user/"+userName+"/queue/notifications"
                        , function (output) {

Но это работает ;-)

[edit] Протоколирование трассировки облегчает понимание происходящего:

  
            
        

Может быть, вам следует создать свой собственный класс модели user principal для определения правильного имени пользователя следующим образом.

public class StompPrincipal implements Principal {
    String name;
    String userid;
  
    public StompPrincipal(String name) {
        this.name = name;
    }
    public String getUserid() {
        return userid;
    }

    public void setUserid(String userid) {
        this.userid = userid;
    }
    @Override
    public String getName() {
        return name;
    }
}

Также необходимо создать реализацию DefaultHandshakeHandler для создания пользователя с выбранным вами именем.

public class CustomHandshakeHandler extends DefaultHandshakeHandler {
    // Custom class for storing principal
    @Override
    protected Principal determineUser(ServerHttpRequest request,
                                      WebSocketHandler wsHandler,
                                      Map attributes) {

        // Generate principal with UUID as name
        return new StompPrincipal(UUID.randomUUID().toString());
    }
}

И наконец, добавьте этот класс CustomHandshakeHandler в метод setHandshakeHandler, как показано ниже

 @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {

        registry.addEndpoint("/ws")
                .setAllowedOrigins("*")
                .setHandshakeHandler(new CustomHandshakeHandler());
    }

2022 WebDevInsider