stomp - spring-websocket STOMP 是否支持 SUBSCRIBE id?

标签 stomp spring-websocket

STOMP 规范规定订阅必须id header

https://stomp.github.io/stomp-specification-1.2.html#SUBSCRIBE_id_Header

SUBSCRIBE id Header

Since a single connection can have multiple open subscriptions with a server, an id header MUST be included in the frame to uniquely identify the subscription. The id header allows the client and server to relate subsequent MESSAGE or UNSUBSCRIBE frames to the original subscription. Within the same connection, different subscriptions MUST use different subscription identifiers.

然而,在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 header 。

我的问题是在给客户端发送消息时如何指定id header?

最佳答案

我认为您不能使用订阅 ID 向特定客户端发送消息。 Stomp 定义了这个 ID,Spring 的实现在内部使用它来为订阅目标地址的每个客户端创建消息。因此,订阅 ID 在 Stomp 通信中是透明的......您可以在客户端指定它或让 Stomp JS(STOMP Over WebSocket)创建一个唯一的。

如果您订阅以“/user/”为前缀的目标并使用 org.springframework.messaging.simp.SimpMessagingTemplate#convertAndSendToUserorg. springframework. messaging. simp . annotation.SendToUser 向单个客户端发送消息,Spring 所做的是根据原始目的地注册并创建对基于自定义 session 的目的地的订阅。换句话说,来自 Spring 的 Javadoc:

When a user attempts to subscribe, e.g. to "/user/queue/position-updates", the "/user" prefix is removed and a unique suffix added based on the session id, e.g. "/queue/position-updates-useri9oqdfzo" to ensure different users can subscribe to the same logical destination without colliding.

When sending to a user, e.g. "/user/{username}/queue/position-updates", the "/user/{username}" prefix is removed and a suffix based on active session id's is added, e.g. "/queue/position-updates-useri9oqdfzo".

参见 http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/messaging/simp/user/DefaultUserDestinationResolver.html

参见 https://docs.spring.io/spring/docs/current/spring-framework-reference/html/websocket.html#websocket-stomp-user-destination

编辑:

您不能使用订阅 ID 直接向其订阅的客户端发送消息,但可以使用客户端的 session ID。根据here ,您可以使用用户的姓名向他发送消息。但是您需要与 Principal 进行身份验证的 session 。或者您可以在消息的 header 中强制使用目标的 session 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());
}

这样做,如果 session 中没有 Principal,我将无法使用 @SendToUser 注释。

关于stomp - spring-websocket STOMP 是否支持 SUBSCRIBE id?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44857585/

相关文章:

spring - Websocket java 客户端 Spring + Stomp : Transport error: ConnectionLostException

java - Spring websocket 从多个线程发送消息

Spring Websocket STOMP 负载测试

java - 无法使用 Spring Websocket 将客户端连接到服务器

java - 无法通过 Spring Boot 通过 STOMP 连接到 ActiveMQ 代理

websocket - 如何使用 Spring Stomp 拦截连接和订阅

permissions - 了解 Rabbitmq 权限

java - 使用 StompClient 在 Spring WebSocket 上传递消息时出错

Java Spring STOMP : Set broker IP

javascript - 如何通过spring websocket向特定设备发送消息