15

我有一个带有 websocket 功能的简单 spring 应用程序,到目前为止一切正常。现在我想使用 @SendToUser 注释从我的服务器向特定客户端发送一条消息。这给了我错误“忽略消息,没有可用的主体信息”。我知道我的服务器上没有任何登录,所以每个用户都是“匿名的”并且没有主体(我现在没有使用 spring security)。但是每个用户都有一个会话 ID。是否可以以某种方式使用会话 ID 来区分用户?我怎样才能做到这一点,以便我的用户获得与会话 ID 对应的主体?

4

5 回答 5

15

订阅时使用@SendToUser并在队列前添加“/user/”(仅限订阅方)。休息很神奇:-)

代替

Java Server: @SendTo("/topic/showResult")

JS Client: stompClient.subscribe('/topic/showResult', function(calResult){  ....

利用:

Java Server: @SentToUser("/topic/showResult")

JS Client: stompClient.subscribe('/user/topic/showResult', function(calResult){ ....

于 2014-10-07T18:30:06.647 回答
10

我认为一个解决方案可能是避免使用@SendToUser和使用 rawSimpMessagingTemplate并将消息发送到您为打开会话控制的目标。

例如。假设您对新的 websocket 会话有一些身份,您可以使用队列名称中的该标识符订阅队列:

stomp.subscribe("/queue/chats" + "-" + mycustomidentifier, onmessage);

现在,在 Spring websocket 侦听器端,您可以使用以下命令引导您的响应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());
    }
....
于 2014-08-01T16:47:16.587 回答
7

基于Biju 的回答并使用Stomp 生成的会话 ID(感谢mariusz2108 在他对类似问题的回答中),这对我有用(基于Spring 的规范示例

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()));
}

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);
        });
    });
}

您可以使用 Web 容器的会话 ID(例如 JSESSIONID)代替 Stomp 会话 ID,但现在默认情况下无法从 JavaScript(对于 Tomcat)访问 cookie,这是一个更困难的前景。

于 2017-04-15T20:06:58.670 回答
2

尝试这个。它对我有用

@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);
}
于 2018-11-01T21:12:00.307 回答
0

这个解决方案对我有用。

上下文:您的应用程序中没有安全性,您想通过 session-id 向用户发送消息。在我们的例子中,另一个词user-id=session-id

private final SimpMessageSendingOperations template;

@MessageMapping("/test")
public void testNotification(@Header("simpSessionId") String sessionId, String name) {
    String payload = "Hello, " + name + "!";
    template.convertAndSendToUser(sessionId, "/ws/notification/message", payload, createHeaders(sessionId));
}

private MessageHeaders createHeaders(String sessionId) {
    SimpMessageHeaderAccessor headerAccessor = SimpMessageHeaderAccessor.create(SimpMessageType.MESSAGE);
    headerAccessor.setSessionId(sessionId);
    headerAccessor.setLeaveMutable(true);
    return headerAccessor.getMessageHeaders();
}

并以这种方式显示 javascript 片段:

stompClient.connect(header, function (frame) {
    console.log('Connected: ' + frame);
    stompClient.subscribe('/user/ws/notification/message', function (greeting) {
        console.log(greeting.body);
    });
});
于 2021-03-25T16:30:48.490 回答