在哪里“用户”来自于convertAndSendToUser在SockJS + Spring Websocket中工作? [英] Where "user" comes from in convertAndSendToUser works in SockJS+Spring Websocket?

查看:572
本文介绍了在哪里“用户”来自于convertAndSendToUser在SockJS + Spring Websocket中工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想了解convertAndSendToUser如何在Spring SockJS + Websocket框架中工作。

I would like to understand how convertAndSendToUser works in Spring SockJS+Websocket framework.

在客户端,我们将连接为

In client, we would connect as

stompClient.connect(login, password, callback())

将导致具有登录和密码的Stomp凭证的连接请求,例如可以看到如果我们处理SessionConnectEvent http:// www.sergialmar.com/2014/03/detect-websocket-connects-and-disconnects-in-spring-4/

which will result in connect request with "Stomp credentials" of login and password, that can be seen e.g. if we handle SessionConnectEvent http://www.sergialmar.com/2014/03/detect-websocket-connects-and-disconnects-in-spring-4/

但目前还不清楚我是否这将是服务器端发送操作到队列的用户:

But it remains unclear to me whether this will be the "user" meant in server-side send operation to a queue:

 simpMessagingTemplate.convertAndSendToUser(username, "/queue/reply", message);

我最接近的是读取此线程在Spring Websocket上向特定用户发送消息,由Thanh Nguyen Van回答,但目前还不清楚。

The closest I can get is to read this thread Sending message to specific user on Spring Websocket, answer by Thanh Nguyen Van, but it is still unclear.

基本上我需要做的是订阅一些客户端到同一主题,但在服务器上,发送不同的数据。客户可以提供用户标识符。

Basically what I need to do, is to subscribe some clients to same topic, but on server, send them different data. Client may supply user identifier.

推荐答案

我一直在尝试理解websockets并遇到了这个问题。没有找到答案,我感到非常失望。这是未来读者的一些东西。

I have been trying to understand websockets and came across this question. Was thoroughly disappointed not to find an answer. Here's something for future reader.

我将假设读者对使用Stomp的弹簧腹板有基本的了解。可以理解订阅,目标前缀,主题,套接字配置文件等术语。

I will assume the reader has a basic understanding of spring websockets using Stomp. Terms like subscription, destination prefixes, topics, socket configuration file etc. are understood.

我们知道我们可以使用主题前缀从stomp服务器向客户端发送消息订阅了例如 /主题/你好。我们也知道我们可以向特定用户发送消息,因为spring提供 convertAndSendToUser(用户名,目的地,消息) API。它接受一个String用户名,这意味着如果我们以某种方式为每个连接都有一个唯一的用户名,我们应该能够向订阅某个主题的特定用户发送消息。

We know we can send messages to client from a stomp server using the topic prefixes that he is subscribed to e.g. /topic/hello. We also know we can send messages to a specific user because spring provides the convertAndSendToUser(username, destination, message) API. It accepts a String username which means if we somehow have a unique username for every connection, we should be able to send messages to specific users subscribed to a topic.

不太了解的是,这个用户名来自哪里?

此用户名是 java.security的一部分.Principal interface。每个 StompHeaderAccessor WebSocketSession 对象都有此实例principal,您可以从中获取用户名。但是,根据我的实验,它不是自动生成的。 必须由服务器为每个会话手动生成。

This username is part of a java.security.Principal interface. Each StompHeaderAccessor or WebSocketSession object has instance of this principal and you can get the user name from it. However, as per my experiments, it is not generated automatically. It has to be generated manually by the server for every session.

要首先使用此界面,您需要实现它。

To use this interface first you need to implement it.

class StompPrincipal implements Principal {
    String name

    StompPrincipal(String name) {
        this.name = name
    }

    @Override
    String getName() {
        return name
    }
}

然后你可以通过覆盖DefaultHandshakeHandler为每个连接生成一个唯一的 StompPrincipal 。您可以使用任何逻辑来生成用户名。下面是一个使用UUID的潜在逻辑:

Then you can generate a unique StompPrincipal for every connection by overriding the DefaultHandshakeHandler. You can use any logic to generate the username. Here is one potential logic which uses UUID :

class CustomHandshakeHandler extends DefaultHandshakeHandler {
    // Custom class for storing principal
    @Override
    protected Principal determineUser(ServerHttpRequest request,
                                      WebSocketHandler wsHandler,
                                      Map<String, Object> attributes) {
        // Generate principal with UUID as name
        return new StompPrincipal(UUID.randomUUID().toString())
    }
}

最后,您需要配置您的websockets以使用您的自定义握手处理程序。

Lastly, you need to configure your websockets to use your custom handshake handler.

@Override
void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
    stompEndpointRegistry
         .addEndpoint("/stomp") // Set websocket endpoint to connect to
         .setHandshakeHandler(new CustomHandshakeHandler()) // Set custom handshake handler
         .withSockJS() // Add Sock JS support
}

这是它。现在,您的服务器配置为为每个连接生成唯一的主体名称。它会将该主体作为 StomHeaderAccessor 对象的一部分传递,您可以通过连接事件侦听器,MessageMapping函数等访问这些对象......

That's It. Now your server is configured to generate a unique principal name for every connection. It will pass that principal as part of StomHeaderAccessor objects that you can access through connection event listeners, MessageMapping functions etc...

来自事件侦听器:

@EventListener
void handleSessionConnectedEvent(SessionConnectedEvent event) {
    // Get Accessor
    StompHeaderAccessor sha = StompHeaderAccessor.wrap(event.getMessage())
}

来自消息映射的API

From Message Mapped APIs

@MessageMapping('/hello')
protected void hello(SimpMessageHeaderAccessor sha, Map message) {
    // sha available in params
}

最后一个关于使用 convertAndSendToUser(...)的说明。向用户发送消息时,您将使用类似这样的内容

One last note about using convertAndSendToUser(...). When sending messages to a user, you will use something like this

convertAndSendToUser(sha.session.principal.name, '/topic/hello', message)

但是,对于订阅客户端,您将使用

However, for subscribing the client, you will use

client.subscribe('/user/topic/hello', callback)

如果您将客户订阅到 / topic / hello ,您将只收到广播的消息。

If you subscribe the client to /topic/hello you will only receive broadcasted messages.

这篇关于在哪里“用户”来自于convertAndSendToUser在SockJS + Spring Websocket中工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆