当前位置: 首页 > 知识库问答 >
问题:

"user"从哪里来的转换和SockJS Spring WebSocket工作?

袁成化
2023-03-14

我想了解convertAndSendToUser如何在SpringSockJSWebSocket框架中工作。

在客户端中,我们将作为

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

这将导致连接请求与"跺脚凭据"的登录名和密码,这可以看到,例如,如果我们处理SessionConnect事件http://www.sergialmar.com/2014/03/detect-websocket-connects-and-disconnects-in-spring-4/

但是我仍然不清楚这是否是服务器端发送操作中的“用户”:

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

我能得到的最接近的是阅读这篇文章在Spring网络插座上向特定用户发送消息,由Thanh Nguyen Van回答,但仍不清楚。

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

共有3个答案

刘明朗
2023-03-14
匿名用户

类似于Winneguen,我可以通过在Message映射方法中注入主体来完成

public void processMessageFromClient(@Payload String message, Principal principal) {

principal.getName()实现来自org.springframework.security.authentication.UsernamePasswordAuthentiationToken类

鱼恩
2023-03-14

我没有做任何特定的配置,我可以这样做:

@MessageMapping('/hello')
protected void hello(Principal principal, Map message) {
    String username = principal.getName();
}
谢泉
2023-03-14

我们知道,我们可以使用客户订阅的主题前缀从stomp服务器向客户发送消息,例如/topic/hello。我们还知道我们可以向特定用户发送消息,因为spring提供了convertAndSendToUser(用户名、目的地、消息)API。它接受一个html" target="_blank">字符串用户名,这意味着如果每个连接都有一个唯一的用户名,我们应该能够向订阅某个主题的特定用户发送消息。

不太清楚的是,这个用户名来自哪里?

此用户名是java的一部分。安全主体接口。每个StompHeaderAccessorWebSocketSession对象都有此主体的实例,您可以从中获取用户名。然而,根据我的实验,它不是自动生成的。它必须由服务器为每个会话手动生成。

要首先使用这个接口,您需要实现它。

class StompPrincipal implements Principal {
    String name

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

    @Override
    String getName() {
        return name
    }
}

然后,您可以通过覆盖DefaultHandshakeHandler为每个连接生成唯一的StompPrincipal。您可以使用任何逻辑来生成用户名。下面是一个使用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())
    }
}

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

@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
}

就这样。现在,服务器配置为为为每个连接生成唯一的主体名称。它将该主体作为StompHeaderAccessor对象的一部分传递,您可以通过连接事件侦听器、消息映射函数等访问这些对象。。。

从事件侦听器:

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

从消息映射API

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

关于使用convertAndSendToUser(…)的最后一点注意事项 。当向用户发送消息时,您将使用以下内容

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

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

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

如果您向客户端订阅/topic/hello,您将只接收广播消息。

 类似资料:
  • 我正在学习node.js,使用Visual Studio代码。在我的项目中,我安装了下划线. js,所以我的node_modules文件夹如下所示: 这是我的索引。js文件: 现在,当我按住Ctrl键单击index.js中的< code>contains函数(在Visual Studio代码中表示“转到定义”)时,它不显示< Code > node _ modules/下划线. js中的conta

  • 本文向大家介绍字符串从哪里来的split方法和length属性?相关面试题,主要包含被问及字符串从哪里来的split方法和length属性?时的应答技巧和注意事项,需要的朋友参考一下 按照我的理解来说,字符串本身是没有相关方法的,主要是字符串在调用String相关的方法过程中,js会将string类型转化为String对象,String原型上挂载了响应的方法。 有误解的话还请指正

  • 如果我在我的应用程序中包含以下J2EE依赖项,我就可以访问servlet和JAX-RS类和接口: 但是它们是从哪里来的呢?在Maven Central上,我看到作为依赖项,这又作为依赖项和,所以从表面上看,这就是答案。 但是所有这些依赖项都被标记为,这意味着作为传递依赖项,除非我明确包含它们,否则它们不会在我的项目中显示。但我的程序编译时只需依赖。为什么? 这是我的依赖树;我不知道他们从哪里进来:

  • 在我们的应用程序中,我们使用InstanceProfileCredentialsProvider访问AmazonS3存储桶,但在我们的一些环境中,凭据被弄乱了。 AWS文件(https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/java-dg-roles.html)内容如下: 如果应用程序使用默认构造函数创建AWS客户端,则客户端将

  • 问题内容: 我到处都在搜寻,但似乎找不到清晰的答案… 服务器(我的问题是glassfish)注入用@Context注释的实际objets的机制是什么?更具体地说,如果我想编写一个类似以下内容的类: 那我该怎么办呢?实例化MyObject的位置在哪里,由谁执行,如何执行? 编辑:我看过类似以下内容: 在JAX-RS中使用@ Context,@Provider和ContextResolver http

  • 问题内容: 我正在寻找一种删除表1中记录的表,其中记录与表2中的“ stn”和“ jaar”匹配。表2中“ jaar”列的内容在上一阶段/查询中的格式为 年(基准)AS’jaar’ 抱歉,找不到我找到该“解决方案”的网站。 问题答案: 您可以使用以下方法实现此目的: