Spring Websockets @SendToUser sans connexion ?
-
02-01-2020 - |
Question
J'ai une application Spring simple avec une fonctionnalité Websocket et tout fonctionne jusqu'à présent.Maintenant, je souhaite envoyer un message de mon serveur à un client spécifique en utilisant l'annotation @SendToUser.Cela me donne l'erreur "Message ignoré, aucune information principale disponible".Je comprends que je n'ai aucun identifiant sur mon serveur, donc chaque utilisateur est "anonyme" et n'a pas de principal (je n'utilise pas Spring Security pour l'instant).Mais chaque utilisateur a un identifiant de session.N'est-il pas possible d'utiliser l'identifiant de session d'une manière ou d'une autre pour différencier les utilisateurs ?Comment puis-je y parvenir pour que mes utilisateurs obtiennent un principal qui correspond à l'identifiant de session ?
La solution
Je pense qu'une solution peut être d'éviter d'utiliser @SendToUser
et d'utiliser RAW SimpMessagingTemplate
et d'envoyer des messages à une destination que vous contrôlez pour des sessions ouvertes.
pour par exemple.En supposant que vous ayez eu une identité pour une nouvelle session WebSocket, vous pouvez vous abonner à une file d'attente avec cet identifiant dans le nom de la file d'attente:
stomp.subscribe("/queue/chats" + "-" + mycustomidentifier, onmessage);
MAINTENANT, sur le côté STRESTER STOCKETTER, vous pouvez diriger vos réponses à l'aide de 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());
}
....
Autres conseils
Utiliser @SendToUser
et ajoutez "/user/" devant la file d'attente lors de l'abonnement (uniquement côté abonné).Le repos fonctionne par magie :-)
Au lieu de
Java Server: @SendTo("/topic/showResult")
et
JS Client: stompClient.subscribe('/topic/showResult', function(calResult){ ....
utiliser:
Java Server: @SentToUser("/topic/showResult")
et
JS Client: stompClient.subscribe('/user/topic/showResult', function(calResult){ ....
bâtiment sur Réponse de Biju et à l'aide de l'ID de session généré par piétonnement (merde> (merci,
Client 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()));
}
Client 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);
});
});
}
au lieu de l'ID de session de Stomp, vous pouvez utiliser votre identifiant de session de votre conteneur Web (par exemple, JSessionID), mais maintenant que le cookie est non accessible par défaut accessibleDe JavaScript (pour Tomcat), c'est une perspective plus difficile.
Essayez ceci.Cela a fonctionné pour moi
@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);
}