O Spring @SubscribeMapping realmente inscreve o cliente em algum tópico?
Estou usando o Spring Websocket com o STOMP, Simple Message Broker. No meu@Controller
Eu uso em nível de método@SubscribeMapping
, que deve inscrever o cliente em um tópico para que o cliente receba as mensagens desse tópico posteriormente. Digamos que o cliente assine o tópico"bate-papo":
stompClient.subscribe('/app/chat', ...);
Como o cliente se inscreveu"/ app / chat", ao invés de"/ topic / chat", essa assinatura iria para o método mapeado usando@SubscribeMapping
:
@SubscribeMapping("/chat")
public List getChatInit() {
return Chat.getUsers();
}
Aqui está o que Primavera ref. diz:
Por padrão, o valor de retorno de um método @SubscribeMapping é enviado como uma mensagem diretamente de volta ao cliente conectado e não passa pelo broker. Isso é útil para implementar interações de mensagens de solicitação-resposta; por exemplo, para buscar dados do aplicativo quando a interface do usuário do aplicativo estiver sendo inicializada.
Ok, era isso que eu queria, mas apenasparcialmente!! Enviando alguns dados init após a inscrição, também. Mas e quantosubscrevendo? Parece-me que a coisa que aconteceu aqui é apenas umapedido-resposta, como um serviço. A assinatura é apenas consumida. Por favor, esclareça-me se for esse o caso.
O cliente se inscreveu em algum local onde o corretor não está envolvido?Se mais tarde eu quiser enviar alguma mensagem para os assinantes de "bate-papo", o cliente a receberá? Parece que não.Quem realiza as assinaturas realmente? Corretor? Ou alguém mais?Se aqui o cliente não está sendo inscrito em nenhum lugar, eu me pergunto por que chamamos isso de "inscrição"; porque o cliente recebe apenas uma mensagem e não mensagens futuras.
EDITAR:
Para garantir que a assinatura seja realizada, tentei o seguinte:
Lado do servidor:
Configuração:
@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();
}
}
Controlador:
@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" + "!");
}
}
CLIENTE:
...
stompClient.subscribe('/topic/greetings', function(greeting){
console.log('RECEIVED !!!');
});
stompClient.send("/app/hello", {}, JSON.stringify({ 'name': name }));
...
O que eu gostaria que acontecesse:
Quando o cliente assina '/topic/greetings
', o métodotry1
É executado.Quando o cliente envia uma mensagem para '/app/hello
', deve receber a mensagem de saudação que seria@SendTo
'/topic/greetings
'Resultados:
Se o cliente assinar/topic/greetings
, o métodotry1
é incapaz de pegá-lo.
Quando o cliente envia uma mensagem para '/app/hello
',greeting
O método foi executado e o cliente recebeu a mensagem de cumprimentos. Então entendemos que ele havia sido inscrito em "/topic/greetings
corretamente.
Mas lembre-se de que 1. falhou. Após algumas tentativas, foi possível quando o cliente se inscreveu no'/app/topic/greetings'
, ou seja, prefixado com/app
(Isso é compreensível por configuração).
Agora 1. está funcionando, mas desta vez 2. falhou: quando o cliente envia uma mensagem para '/app/hello
', sim,greeting
O método foi executado, mas o cliente NÃO recebeu a mensagem de saudação. (Como provavelmente agora o cliente foi inscrito no tópico prefixado com '/app
', que era indesejado.)
Então, o que eu consegui é 1 ou 2 do que eu gostaria, mas não esses 2 juntos.
Como faço para conseguir isso com essa estrutura (configurando os caminhos de mapeamento corretamente)?