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
相关文章:
springboot整合websocket,超简单入门
springBoot整合webSocket,超简单入门 webSocket简洁 WebSocket 是一种基于 TCP 协议的全双工通信协议,它允许客户端和服务器之间建立持久的、双向的通信连接。相比传统的 HTTP 请求 - 响应模式,WebSocket 提供了实时、低延迟的数据传输能力。…...
代码随想录算法训练营第三十四天| 860.柠檬水找零 406.根据身高重建队列 452. 用最少数量的箭引爆气球
860.柠檬水找零 题目链接 思路 三种情况,一种贪心,在bill为20时,有一次贪心选择:优先考虑先找105,再考虑找3*5,因为5可以用于bill10和bill20两种情况 解题方法 第一种:bill5,直接收 第二种…...
ICode国际青少年编程竞赛- Python-2级训练场-识别循环规律2
ICode国际青少年编程竞赛- Python-2级训练场-识别循环规律2 1、 for i in range(3):Dev.step(3)Dev.turnRight()Dev.step(4)Dev.turnLeft()2、 for i in range(3):Spaceship.step(3)Spaceship.turnRight()Spaceship.step(1)3、 Dev.turnLeft() Dev.step(Dev.x - Item[1].…...
12.轻量级锁原理及其实战
文章目录 轻量级锁原理及其实战1.轻量级锁的核心原理2.轻量级锁的演示2.1.轻量级锁的演示代码2.2.结果分析 3.轻量级锁的分类3.1.普通自旋锁3.2.自适应自旋锁 4.轻量级锁的膨胀 轻量级锁原理及其实战 引入轻量级锁的主要目的是在多线程环境竞争不激烈的情况下, 通过…...
栈结构(c语言)
1.栈的概念 栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。 压栈&am…...
【C++】C/C++中新const用法:const成员
欢迎来到CILMY23的博客 本篇主题为: C/C中新const用法:const成员 个人主页:CILMY23-CSDN博客 系列专栏:Python | C | C语言 | 数据结构与算法 | 贪心算法 | Linux 感谢观看,支持的可以给个一键三连,点赞…...
武汉凯迪正大—钢管焊缝裂纹探伤仪
产品概述 武汉凯迪正大无损探伤仪是一种便携式工业无损探伤仪器, 能够快速便捷、无损伤、精确地进行工件内部多种缺陷(裂纹、夹杂、气孔等)的检测、定位、评估和诊断。既可以用于实验室,也可以用于工程现场。 设置简单,…...
为什么 IP 地址通常以 192.168 开头?
在网络配置中,我们经常会遇到以 192.168 开头的 IP 地址,例如 192.168.0.1 或者 192.168.1.100。 这些地址通常用于局域网中,但为什么要选择以 192.168 开头呢? 本文将深入探讨这个问题,并解释其背后的原因和历史渊源…...
elementUi中的el-table合计行添加点击事件
elementUi 文档中,合计行并没有点击事件,这里自己实现了合计行的点击事件。 created() {this.propertyList [{ property: order, label: 序号 },{ property: deptName, label: 单位名称 },{ property: contentPublishQuantity, label: 文章数量 },{ pro…...
Zookeeper集群搭建的一些问题
问题描述一: Cannot open channel to 2 at election address /192.168.60.132:3888解决方案: 查看zookeeper配置文件zoo.cfg / zoo_sample.cfg中集群配置部分 server.1zoo1-net1:2888:3888|zoo1-net2:2889:3889 server.2zoo2-net1:2888:3888|zoo2-net2…...
【线性代数】俗说矩阵听课笔记
基础解系的概念 线性方程组的解 21行列式和矩阵秩Rank的等价刻画 子式 标准型 利用子式求解矩阵的rank 24零积秩不等式 齐次线性方程组的基础解系 rank的两个重要结论 ¥25伴随矩阵的rank 奇异矩阵:行列式0的矩阵 31线性相关,线性无关&#…...
物联网技术在数字化工厂中的应用,你知道多少?——青创智通
工业物联网解决方案-工业IOT-青创智通 物联网(IoT)技术在数字化工厂的应用正日益成为工业革命的重要推动力。随着科技的飞速发展,物联网技术不断革新,其在数字化工厂中的应用也呈现出愈发广泛和深入的态势。本文将详细探讨物联网…...
nacos开启登录开关启动报错“Unable to start embedded Tomcat”
nacos 版本:2.3.2 2.2.2版本之前的Nacos默认控制台,无论服务端是否开启鉴权,都会存在一个登录页;在之后的版本关闭了默认登录页面,无需登录直接进入控制台操作。在这里我们可以在官网可以看到相关介绍 而我现在所用的…...
Linux|了解如何使用 awk 内置变量
引言 当我们揭开 Awk 功能部分时,我们将介绍 Awk 中内置变量的概念。您可以在 Awk 中使用两种类型的变量:用户定义的变量和内置变量。 内置变量的值已经在 Awk 中定义,但我们也可以仔细更改这些值,内置变量包括: FILEN…...
代码随想录-算法训练营day29【回溯算法05:递增子序列、全排列】
代码随想录-035期-算法训练营【博客笔记汇总表】-CSDN博客 第七章 回溯算法part05* 491.递增子序列 * 46.全排列 * 47.全排列 II详细布置 491.递增子序列 本题和大家刚做过的 90.子集II 非常像,但又很不一样,很容易掉坑里。 https://programmercarl.com…...
704. 二分查找
Problem: 704. 二分查找 🐷我的leetcode主页 文章目录 题目分类思路什么是二分查找如何理解时间复杂度 解题方法Code 题目 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target&a…...
php回车变br、php显示br
在 PHP 中,如果你想将回车符(\n)转换为 HTML 的 <br> 标签来实现换行显示,可以使用内置函数 nl2br()。这个函数会将文本中的换行符替换为 <br> 标签。以下是使用 nl2br() 函数的示例代码: <?php $tex…...
找最大数字-第12届蓝桥杯国赛Python真题解析
[导读]:超平老师的Scratch蓝桥杯真题解读系列在推出之后,受到了广大老师和家长的好评,非常感谢各位的认可和厚爱。作为回馈,超平老师计划推出《Python蓝桥杯真题解析100讲》,这是解读系列的第60讲。 找最大数字&#…...
蓝桥杯 算法提高 ADV-1170 阶乘测试 python AC
找规律题,遍历i中有几个m就加几,和m的多少次数有关 第一版👇 try:while True:n, m map(int, input().split())ll [i for i in range(1, n 1) if i % m 0]ans len(ll)M mwhile ll:lll []M * mfor i in ll:if i % M 0:lll.append(i)a…...
阿里巴巴杭州全球总部正式启用,创新“减碳大脑”科技减碳 | 最新快讯
来源:封面新闻 封面新闻记者付文超 5 月 10 日,记者获悉,位于未来科技城的阿里巴巴杭州全球总部新园区正式启用,这是阿里巴巴目前最大的综合性办公园区。从空中俯瞰,园区正中央呈现阿里标志性的笑脸 logo,这…...
轻舟体重管理大模型:赋能减重全病程管理,构建智能体重健康生态
在“健康中国2030”战略深入推进的背景下,慢性病防控与全民体重管理已成为公共卫生体系的重要议题。随着肥胖及相关代谢性疾病发病率持续上升,传统的体重干预模式已难以满足全人群、全生命周期的健康管理需求。在此趋势下,基于人工智能技术的…...
Python原生AOT编译2026架构设计图(含C-API二进制兼容性矩阵+GC停顿压缩至≤80μs实证)
第一章:Python原生AOT编译2026架构全景概览Python原生AOT(Ahead-of-Time)编译在2026年已演进为一套融合语言语义、运行时契约与硬件感知能力的系统级基础设施。它不再依赖传统解释器或JIT中间态,而是通过静态类型推导、控制流图全…...
[AI/Agent/社交] AI Agent社交网络产品:MoltBook => InStreet
Julia(julialang.org)由Stefan Karpinski、Jeff Bezanson等在2009年创建,目标是融合Python的易用性、C的高性能、R的统计能力、Matlab的科学计算生态。 其核心设计哲学是: 高性能:编译型语言(JIT࿰…...
老马失前蹄,竟然在数据库外键上翻车了,重温外键级联
一、什么是setuptools? setuptools 是一个用于创建、分发和安装 Python 包的核心库。 它可以帮助你: 定义 Python 包的元数据(如名称、版本、作者等)。 声明包的依赖项,确保你的包能够正确运行。 构建源代码分发包&…...
MCP3208 12位SPI ADC嵌入式驱动与硬件设计实战
1. MCP3208芯片深度解析:面向嵌入式系统的12位8通道SPI模数转换器工程实践1.1 芯片定位与核心价值MCP3208是Microchip公司推出的逐次逼近型(SAR)模数转换器,专为资源受限的嵌入式系统设计。其核心价值在于以极简硬件接口ÿ…...
【Java外部函数性能优化黄金法则】:20年JVM专家亲授JNI/FFM调优的7大致命误区与3步极速修复方案
第一章:Java外部函数优化的演进脉络与性能本质Java平台对外部函数调用(Foreign Function & Memory API,即JEP 454/464/471/472)的演进,标志着JVM从“纯Java世界”迈向系统级互操作的新纪元。其性能本质并非单纯降低…...
手把手教你用llama.cpp在树莓派上跑大模型(附完整配置流程)
在树莓派上部署llama.cpp的完整实践指南 树莓派作为一款价格亲民且功能强大的微型计算机,近年来在边缘计算和嵌入式AI领域崭露头角。本文将详细介绍如何在树莓派上部署llama.cpp这一轻量级大语言模型推理框架,让开发者能够在资源受限的环境中体验前沿AI技…...
爬虫自动化(DrissionPage)
目录 ?一.介绍: 下载DrissionPage,还是我们熟悉的pip: 环境准备: ?二.基本代码: 它对于的导包和类使用: 窗口的设置: 和获取的页面的滑动: 3.进一步认识DrissionPage: 浏览器可以多开…...
光流法在气象雷达中的应用:从原理到外推实践
光流法在气象雷达中的应用:从原理到外推实践 气象雷达作为现代气象监测的核心工具,其回波数据蕴含着丰富的天气系统动态信息。如何从这些看似静态的图像序列中提取运动规律,进而预测未来短时内的天气变化,一直是气象学界和工程界关…...
实战指南:运用快马平台与mcp协议构建企业级智能数据分析系统
今天想和大家分享一个最近用InsCode(快马)平台实现的实战项目——基于MCP协议的企业级智能数据分析系统。这个项目特别适合需要整合多源数据的企业场景,整个过程让我深刻体会到MCP协议在复杂系统中的桥梁作用,以及快马平台如何让这类应用的开发部署变得异…...
