Pergunta

Eu tenho um aplicativo Spring simples com funcionalidade websocket e tudo funciona até agora.Agora quero enviar uma mensagem do meu servidor para um cliente específico usando a anotação @SendToUser.Isso me dá o erro "Ignorando mensagem, nenhuma informação principal disponível".Entendo que não tenho nenhum login no meu servidor, portanto cada usuário é "anônimo" e não possui um principal (não estou usando o Spring Security por enquanto).Mas cada usuário possui um ID de sessão.Não é possível usar o ID da sessão de alguma forma para diferenciar os usuários?Como posso conseguir isso para que meus usuários obtenham um principal que corresponda ao ID da sessão?

Foi útil?

Solução

Acho que uma solução seria evitar o uso @SendToUser e use cru SimpMessagingTemplate e para enviar mensagens para um destino que você controla para sessões abertas.

Por exemplo.supondo que você tenha alguma identidade para uma nova sessão de websocket, você pode se inscrever em uma fila com esse identificador no nome da fila:

stomp.subscribe("/queue/chats" + "-" + mycustomidentifier, onmessage);

Agora, no lado do ouvinte do websocket Spring, você pode direcionar suas respostas usando SimpMessagingTemplate:

@Controller
public class MyController {


    @Autowired
    private SimpMessagingTemplate simpMessagingTemplate;

    @MessageMapping("/chats")
    public void handleChat(@Payload ChatMessage message) {
        this.simpMessagingTemplate.convertAndSend("/queue/chats-" + "mycustomidentifier", "[" + getTimestamp() + "]:" + message.getMessage());
    }
....

Outras dicas

Usar @SendToUser e adicione "/user/" na frente da fila ao se inscrever (somente no lado do assinante).O descanso faz mágica :-)

Em vez de

Java Server: @SendTo("/topic/showResult")

e

JS Client: stompClient.subscribe('/topic/showResult', function(calResult){  ....

usar:

Java Server: @SentToUser("/topic/showResult")

e

JS Client: stompClient.subscribe('/user/topic/showResult', function(calResult){ ....

Construindo em A resposta de Biju e usando o ID de sessão gerado pelo Stomp (obrigado, mariusz2108 em sua resposta a uma pergunta semelhante), aqui está o que funcionou para mim (com base em o exemplo canônico do Spring)

Cliente SpringFramework:

private SimpMessagingTemplate template;

@Autowired
public GreetingController(SimpMessagingTemplate template) {
    this.template = template;
}

@MessageMapping("/hello")
public void greeting(HelloMessage message, @Header("simpSessionId") String sessionId) throws Exception {
    template.convertAndSend("/queue/greeting-"+sessionId, new Greeting("Hello, " + message.getName()));
}

Cliente JavaScript:

function connect() {
    var socket = new SockJS('/gs-guide-websocket');
    stompClient = Stomp.over(socket);
    stompClient.connect({}, function (frame) {
        var sessionId = /\/([^\/]+)\/websocket/.exec(socket._transport.url)[1];
        console.log("connected, session id: " + sessionId);
        stompClient.subscribe('/queue/greeting-'+sessionId, function (greeting) {
            showGreeting(JSON.parse(greeting.body).content);
        });
    });
}

Em vez do ID de sessão do Stomp, você pode usar o ID de sessão do seu contêiner da web (por exemplo,JSESSIONID), mas agora esse cookie é não é acessível por padrão a partir de JavaScript (para Tomcat) esta é uma perspectiva mais difícil.

Experimente isso.Funcionou para mim

@Autowired
private SimpMessagingTemplate messagingTemplate;

@MessageMapping("/getHello")
public void sendReply( MessageHeaders messageHeaders, @Payload String message, @Header(name = "simpSessionId") String sessionId){
        messagingTemplate.convertAndSendToUser(sessionId, "/queue/hello", "Hello "+ message, messageHeaders);
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top