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

springboot整合websocket,超简单入门

springBoot整合webSocket,超简单入门

webSocket简洁

WebSocket 是一种基于 TCP 协议的全双工通信协议,它允许客户端和服务器之间建立持久的、双向的通信连接。相比传统的 HTTP 请求 - 响应模式,WebSocket 提供了实时、低延迟的数据传输能力。通过 WebSocket,客户端和服务器可以在任意时间点互相发送消息,实现实时更新和即时通信的功能。WebSocket 协议经过了多个浏览器和服务器的支持,成为了现代 Web 应用中常用的通信协议之一。它广泛应用于聊天应用、实时数据更新、多人游戏等场景,为 Web 应用提供了更好的用户体验和更高效的数据传输方式。

1、导包

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency>

2、写配置类

@Configuration
public class WebSocketConfig {/*** 	注入ServerEndpointExporter,* 	这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint*/@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}}

3、创建ServerEndpoint 端点

服务端 WebSocket 端点的开发也有 2 种方式。第 1 种是实现规范所提供的各种接口,通过接口定义的回调方法来处理新的连接、客户端消息、连接断开等等事件。另一种方式是使用注解,类似于 Spring 中的 Controller,通过在方法上使用不同的注解来监听不同的 WebSocket 事件,灵活性比较高,推荐使用。

@Component
@Slf4j
@ServerEndpoint("/websocket/{userId}")  // 接口路径 ws://localhost:8080/websocket/userId;
public class WebSocket {// 与某个客户端的连接会话,需要通过它来给客户端发送数据private Session session;/*** 用户ID*/private String userId;// concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。// 虽然@Component默认是单例模式的,但springboot还是会为每个websocket连接初始化一个bean,所以可以用一个静态set保存起来。//  注:底下WebSocket是当前类名private static final CopyOnWriteArraySet<WebSocket> webSockets = new CopyOnWriteArraySet<>();// 用来存在线连接用户信息private static final ConcurrentHashMap<String, Session> sessionPool = new ConcurrentHashMap<>();/*** 链接成功调用的方法*/@OnOpenpublic void onOpen(Session session, @PathParam(value = "userId") String userId) {try {this.session = session;this.userId = userId;webSockets.add(this);sessionPool.put(userId, session);log.info("【websocket消息】有新的连接,总数为:" + webSockets.size());} catch (Exception e) {log.error("onOpen 报错", e);}}/*** 链接关闭调用的方法*/@OnClosepublic void onClose() {try {webSockets.remove(this);sessionPool.remove(this.userId);log.info("【websocket消息】连接断开,总数为:" + webSockets.size());} catch (Exception e) {log.error("onOpen 报错", e);}}/*** 收到客户端消息后调用的方法** @param message*/@OnMessagepublic void onMessage(String message) {log.info("【websocket消息】收到客户端消息:" + message);}/*** 发送错误时的处理** @param session* @param error*/@OnErrorpublic void onError(Session session, Throwable error) {log.error("用户错误,原因:" + error.getMessage());}// 此为广播消息public void sendAllMessage(String message) {log.info("【websocket消息】广播消息:" + message);for (WebSocket webSocket : webSockets) {try {if (webSocket.session.isOpen()) {webSocket.session.getAsyncRemote().sendText(message);}} catch (Exception e) {log.error("sendAllMessage 报错", e);}}}// 此为单点消息public void sendOneMessage(String userId, String message) {Session session = sessionPool.get(userId);if (session != null && session.isOpen()) {try {log.info("【websocket消息】 单点消息: 发给用户【{}】:【{}】",userId,message);session.getAsyncRemote().sendText(message);} catch (Exception e) {log.error("sendOneMessage 报错", e);}}}// 此为单点消息(多人)public void sendMoreMessage(String[] userIds, String message) {for (String userId : userIds) {Session session = sessionPool.get(userId);if (session != null && session.isOpen()) {try {log.info("【websocket消息】 单点消息(多人): 发给用户【{}】:【{}】",userId,message);session.getAsyncRemote().sendText(message);} catch (Exception e) {log.error("sendMoreMessage 报错", e);}}}}
}

4、写controller用于模仿数据刷新

@RestController
@Slf4j
@RequestMapping("web")
public class WebSocketTestController {@Resourceprivate WebSocket webSocket;// 模仿其他的服务调用webSocket进行数据刷新@PostMapping("/test")public Results test(@RequestBody TestDto dto) {log.info("test 入参 dto:{}",dto);try {// 数据返回JSONObject obj = new JSONObject();obj.put("audience",Math.random() * 100);obj.put("msg",dto.getMsg());// 全体发送 自己去测
//        webSocket.sendAllMessage(obj.toJSONString());if (StringUtils.isNotBlank(dto.getUserId())){// 单个用户发送 (userId为用户id)webSocket.sendOneMessage(dto.getUserId(), obj.toJSONString());}if (dto.getUserIds() != null && dto.getUserIds().length > 0){// 多个用户发送 (userIds为多个用户id)webSocket.sendMoreMessage(dto.getUserIds(), obj.toJSONString());}return Results.success();} catch (Exception e) {log.error("test 报错",e);return Results.failed();}}
}
// 偷个懒
@Data
class TestDto{private String userId;private String[] userIds;private String msg;
}

5、测试

使用测试网站:WebSocket在线测试工具 (wstool.js.org)

创建三个用户

在这里插入图片描述

开启连接

在这里插入图片描述

查看日志

在这里插入图片描述

使用postman用于测试

在这里插入图片描述

5.1、测试只要123收到消息

发送:

{"userId":"123","userIds":[],"msg":"are you ok ?"
}

在这里插入图片描述

5.2、测试456、789收到消息

发送:

{"userId":"","userIds":["456","789"],"msg":"6666"
}

在这里插入图片描述

查看日志

在这里插入图片描述

感谢:springboot整合webSocket

http://www.lryc.cn/news/345173.html

相关文章:

  • 代码随想录算法训练营第三十四天| 860.柠檬水找零 406.根据身高重建队列 452. 用最少数量的箭引爆气球
  • ICode国际青少年编程竞赛- Python-2级训练场-识别循环规律2
  • 12.轻量级锁原理及其实战
  • 栈结构(c语言)
  • 【C++】C/C++中新const用法:const成员
  • 武汉凯迪正大—钢管焊缝裂纹探伤仪
  • 为什么 IP 地址通常以 192.168 开头?
  • elementUi中的el-table合计行添加点击事件
  • Zookeeper集群搭建的一些问题
  • 【线性代数】俗说矩阵听课笔记
  • 物联网技术在数字化工厂中的应用,你知道多少?——青创智通
  • nacos开启登录开关启动报错“Unable to start embedded Tomcat”
  • Linux|了解如何使用 awk 内置变量
  • 代码随想录-算法训练营day29【回溯算法05:递增子序列、全排列】
  • 704. 二分查找
  • php回车变br、php显示br
  • 找最大数字-第12届蓝桥杯国赛Python真题解析
  • 蓝桥杯 算法提高 ADV-1170 阶乘测试 python AC
  • 阿里巴巴杭州全球总部正式启用,创新“减碳大脑”科技减碳 | 最新快讯
  • 蓝桥杯国赛练习题真题Java(矩阵计数)
  • 概念解析 | ROC曲线:评估分类模型
  • 数据可视化训练第二天(对比Python与numpy中的ndarray的效率并且可视化表示)
  • 【Java EE】数据库连接池详解
  • 正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-15.4讲 GPIO中断实验-IRQ中断服务函数详解
  • 如何平衡RPA机器人的安全性与业务敏捷性,同时不牺牲用户体验?
  • 地球行星UE5和UE4
  • 7.k8s中的名称空间namespace
  • 上海企业源代码防泄密解决方案,企业源代码防泄密如何应对?
  • 将要上市的自动驾驶新书《自动驾驶系统开发》中摘录各章片段 4
  • OpenSearch 与 Elasticsearch:7 个主要差异及如何选择