messagingTemplate.convertAndSendToUser 消息在前端未收到

问题描述 投票:0回答:1

我希望你们一切都好。我正在学习在 Spring boot 中使用来自 Nodejs 中的 SocketIo 的 Websockets。我正在使用

Stomp client
SimpMessageSendingOperations messagingTemplate 
来回发送消息。

问题是,对于某些代码段,我想排除发送者接收消息。

@SendTo
可以很好地向所有订阅者(包括发件人)发送消息。

经过一番谷歌搜索后,我找到了

messagingTemplate
并尝试使用它但没有成功。

后端发送消息,前端却始终没有收到。

下面是我的代码。我已经尽可能简化了,但我仍然无法使用

messagingTemplate.convertAndSendToUser
接收任何消息。

这是 Web 配置文件:

package com.example.demo.SocketClass;

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.messaging.simp.user.SimpUserRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;


@Configuration
@EnableWebSocketMessageBroker
public class SocketConfig implements WebSocketMessageBrokerConfigurer {
    SimpUserRegistry simpUserRegistry;



    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/ws").withSockJS();
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.setApplicationDestinationPrefixes("/app");
        registry.enableSimpleBroker("/topic");
        registry.setUserDestinationPrefix("/user");

    }


这是前端:

let sessionId;
let getRandom = integer => Math.floor(Math.random()*integer)

let socket = new SockJS('http://localhost:8080/ws',[],{sessionId:8})
var stompClient = Stomp.over(socket)
let username = "john"
stompClient.connect({},stompClientOnConnected, onError)

function stompClientOnConnected(frame){
    stompClient.subscribe(`user/john/topic/ConnectionTest`, onUserMoved)
   

    sessionId = getRandom(10000000).toString()

    setTimeout( () => stompClient.send("/app/draw.ConnectionTest",{},JSON.stringify({ username: 'john' })), 3000)
  
    function onUserMoved (data){ console.log("Data after user moved: ",data) }

}

function onError(err){
    console.log("thats an error :", err)
}

这是控制器:


package com.example.demo.SocketClass;

import com.example.demo.DrawAppUser.DrawAppSession;
import com.example.demo.SocketData.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
import org.springframework.messaging.simp.SimpMessageSendingOperations;
import org.springframework.messaging.simp.SimpMessageType;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.stereotype.Controller;

import java.util.ArrayList;
import java.util.Map;

@Controller
public class SocketController {

    private final SimpMessageSendingOperations messagingTemplate;
    @Autowired
    public SocketController(SimpMessageSendingOperations messagingTemplate){
        this.messagingTemplate= messagingTemplate;
    }


@MessageMapping("/draw.ConnectionTest")
public void userConnectedEvent(SimpMessageHeaderAccessor accessor, @Payload String load) {


    String simpSessionId = accessor.getSessionId();
    System.out.println("Received userConnectedEvent. Session ID: " + simpSessionId);

    String message = "Your session ID is: " + simpSessionId;


    SimpMessageHeaderAccessor responseAccessor =    StompHeaderAccessor.create(SimpMessageType.MESSAGE);
    responseAccessor.setSessionId(simpSessionId);


    System.out.println("Sending message: " + message);
    messagingTemplate.convertAndSendToUser("john", "/topic/ConnectionTest", message, responseAccessor.getMessageHeaders());

}

我尝试使用 sessionId 但没有运气

@MessageMapping("/draw.ConnectionTest")
public void userConnectedEvent(SimpMessageHeaderAccessor accessor, @Payload String load) {


    String simpSessionId = accessor.getSessionId();
    System.out.println("Received userConnectedEvent. Session ID: " + simpSessionId);

    String message = "Your session ID is: " + simpSessionId;


    SimpMessageHeaderAccessor responseAccessor =    StompHeaderAccessor.create(SimpMessageType.MESSAGE);
    responseAccessor.setSessionId(simpSessionId);


    System.out.println("Sending message: " + message);

//
    messagingTemplate.convertAndSendToUser(simpSessionId, "/topic/ConnectionTest", message, responseAccessor.getMessageHeaders());

}

我尝试在函数的开头和结尾处打印。两者都运行正常,但前端没有收到消息。

这是我刷新页面后从浏览器控制台当前获得的信息:

Opening Web Socket...
stomp.min.js:8 Web Socket Opened...
stomp.min.js:8 >>> CONNECT
accept-version:1.1,1.0
heart-beat:10000,10000

<<< CONNECTED
version:1.1
heart-beat:0,0

connected to server undefined

>>> SUBSCRIBE
id:sub-0
destination:user/john/topic/ConnectionTest


connected!!
mytest.js:16 this is frame:  
n {command: 'CONNECTED', headers: {…}, body: ''}

>>> SEND
destination:/app/draw.ConnectionTest
content-length:19

{"username":"john"}

我与chatgbt3.5进行了长时间的对话,它基本上放弃了,并告诉我代码应该可以工作,并且我应该检查我的防火墙。

有什么想法吗?

spring-boot stomp spring-websocket
1个回答
0
投票

在脚本中使用正斜杠 (

/
) 为目的地添加前缀。在你的情况下,它必须是
stompClient.subscribe('/user/john/topic/ConnectionTest", onUserMoved)

并在您的 spring-boot WebSocket 配置文件中,还将

/user
注册为 simpleBroker,如下所示
registry.enableSimpleBroker("/topic", "/user");

SimpMessagingTemplate#convertAndSendToUser
将按如下方式构造目的地
userDestinationPrefix + user + destination
就您而言,您已将 userDestinationPrefix 注册为“/user”。所以convertAndSendToUser会将消息发送到目的地
/user/<username>/destination

© www.soinside.com 2019 - 2024. All rights reserved.