STOMP规范说SUBSCRIBE 必须有 id标头。
https://stomp.github.io/stomp-specification-1.2.html#SUBSCRIBE_id_Header
SUBSCRIBE id标头
由于单个连接可以有多个打开的订阅 服务器,ID头必须唯一地包含在帧中 识别订阅。 id标头允许客户端和服务器 将后续MESSAGE或UNSUBSCRIBE帧与原始帧相关联 订阅。在同一个连接中,不同的订阅必须 使用不同的订阅标识符。
但是,在spring的示例https://spring.io/guides/gs/messaging-stomp-websocket/中,它在订阅目标时没有指定id。
function connect() {
var socket = new SockJS('/gs-guide-websocket');
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
setConnected(true);
console.log('Connected: ' + frame);
stompClient.subscribe('/topic/greetings', function (greeting) {
showGreeting(JSON.parse(greeting.body).content);
});
});
}
在Spring的API中,SimpMessageSendingOperations。 convertAndSendToUser 不会明确支持id标头。
我的问题是如何在向客户端发送邮件时指定ID标头?
答案 0 :(得分:0)
我认为您无法使用订阅ID向特定客户端发送消息。 Stomp定义了这个ID,Spring的实现在内部使用它来为订阅目标地址的每个客户端创建消息。因此,订阅ID在Stomp通信中是透明的...您可以在客户端指定它或让Stomp JS(STOMP Over WebSocket)创建一个唯一的。
如果您订阅了以" / user /&#34为前缀的目的地;并使用org.springframework.messaging.simp.SimpMessagingTemplate#convertAndSendToUser
或org.springframework.messaging.simp.annotation.SendToUser
向单个客户端发送消息,Spring所做的是根据原始目标注册并创建对基于自定义会话的目标的订阅。换句话说,来自Spring的Javadoc:
当用户尝试订阅时,例如至 " / user / queue / position-updates"," / user"删除前缀和 基于会话ID添加的唯一后缀,例如 " /队列/位置更新 - useri9oqdfzo"确保不同的用户可以 订阅相同的逻辑目的地而不会发生冲突。
发送给用户时,例如 " / user / {username} / queue / position-updates"," / user / {username}" 删除前缀并添加基于活动会话ID的后缀, 例如" /队列/位置更新 - useri9oqdfzo"
已编辑:
您无法使用订阅ID直接向其订阅的客户端发送消息,但您可以使用客户端的会话ID。根据{{3}},您可以使用用户的名称向他发送消息。但是你需要一个带有Principal的认证会话。或者您可以在邮件的标题中强制使用目标的会话ID,从而避免内部步骤发现它,如here所示。
private void sendMessageToUser(String destinationSessionId, String message) {
SimpMessageHeaderAccessor headerAccessor = SimpMessageHeaderAccessor.create(SimpMessageType.MESSAGE);
headerAccessor.setSessionId(destinationSessionId);
headerAccessor.setLeaveMutable(true);
messagingTemplate.convertAndSendToUser(destinationSessionId, "/subscribe/private", message, headerAccessor.getMessageHeaders());
}
这样做,在会话中没有校长,我无法使用@SendToUser
注释。