当前位置: 首页 > news >正文

在SockJS+Spring Websocket中convertAndSendToUser中的“用户”来自哪里?

目录

  • 一、前言
  • 二、Principal
  • 三、使用

一、前言

我们知道可以使用客户端订阅的主题前缀从 stomp 服务器向客户端发送消息,例如 /topic/hello。我们还知道我们可以向特定用户发送消息,因为 spring 提供了convertAndSendToUser(username, destination, message)API。它接受一个字符串用户名,这意味着如果我们以某种方式为每个连接都有一个唯一的用户名,我们能够向订阅某个主题的特定用户发送消息。

那么,这个用户名来自哪里?或者说它是如何用这个用户名确定对应连接的?

二、Principal

对于上面的回答是:用户名是 java.security.Principal 的一部分。每个StompHeaderAccessor或WebSocketSession对象都有此主体的实例,我们可以从中获取用户名。但是,它不是自动生成的。它必须由服务器为每个会话手动生成。

要使用它,必须先实现它:

class StompPrincipal implements Principal {String nameStompPrincipal(String name) {this.name = name}@OverrideString getName() {return name}
}

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

class CustomHandshakeHandler extends DefaultHandshakeHandler {@Overrideprotected Principal determineUser(ServerHttpRequest request,WebSocketHandler wsHandler,Map<String, Object> attributes) {return new StompPrincipal(UUID.randomUUID().toString())}
}

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

@Override
void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {stompEndpointRegistry.addEndpoint("/stomp") .setHandshakeHandler(new CustomHandshakeHandler()) //在这里设置.withSockJS() 
}

三、使用

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

来自事件监听器:

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

来自消息映射 API:

@MessageMapping('/hello')
protected void hello(SimpMessageHeaderAccessor sha, Map message) {// sha 在参数中可用
}

使用convertAndSendToUser(…),向用户发送消息时,使用类似这样的内容:

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

但是,要订阅客户端,必须使用:

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

如果要接收广播:

client.subscribe('/topic/hello', callback)
http://www.lryc.cn/news/122947.html

相关文章:

  • 【软件测试】我的2023面试经验谈
  • SpringBoot 整合JDBC
  • TypeScript使用npm安装报错问题
  • 2023国赛数学建模思路 - 复盘:人力资源安排的最优化模型
  • 学习pytorch 3 tensorboard的使用
  • Linux 命令篇
  • OpenCV-SIFT算法详解
  • Java中的接口到底是什么?
  • Jpa与Druid线程池及Spring Boot整合(一): spring-boot-starter-data-jpa 搭建持久层
  • helm部署vmalert
  • 加工厂数字孪生3D可视化展示系统重塑管理模式
  • php从静态资源到动态内容
  • JavaScript:模块化【CommonJS与ES6】
  • Redis—持久化
  • 【设计模式】代理模式
  • mac arm 通过brew搭建 php+nginx+mysql+xdebug
  • 软信天成:告别手动编码,实现智能自动化云数据管理
  • 易基因:ChIP-seq等揭示转录因子NRF1调控原始生殖细胞发育、增殖和存活的表观遗传机制|科研进展
  • 35岁,体能断崖?你需要健康的生活习惯
  • mysql 习题总结
  • IL汇编语言做一个窗体
  • 不用技术代码,分班查询系统怎么做?
  • 【Mybatis】调试查看执行的 SQL 语句
  • 【多视重建】从Zero-123到One-2-3-45:多视角生成
  • (四)Unity开发Vision Pro——参考文档
  • 【Linux】简单线程池的设计与实现 -- 单例模式
  • [RoarCTF 2019Online Proxy]sql巧妙盲注
  • flutter开发实战-just_audio实现播放音频暂停音频设置音量等
  • 【Bert101】最先进的 NLP 模型解释【01/4】
  • c语言经典例题讲解(输出菱形,喝汽水问题)