spring boot整合WebSocket实现群聊功能 通俗易懂教程

  1. 首先获取消息的内容,即payload。
  2. 将payload转换为JSONObject对象,并从中获取消息类型type。
  3. 如果消息类型是"join",则从消息中获取群组ID,并将当前WebSocketSession的ID加入到该群组对应的Set中。
  4. 如果消息类型是"leave",则从消息中获取群组ID,并从该群组对应的Set中移除当前WebSocketSession的ID。
  5. 如果消息类型是"message",则从消息中获取群组ID,并获取该群组对应的所有WebSocketSession,逐一向这些Session发送消息。

其中,groups和sessions是两个Map,分别用来存储群组与其对应的WebSocketSessions。computeIfAbsent和computeIfPresent方法分别用来向Map中添加元素和更新元素。sendMessage方法用来向客户端发送消息。

导入依赖

        <!-- spring-boot-starter-websocket依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency>
创建MyWebSocketHandler类
import com.songzixain.service.MyWebSocketHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;/*** <p>* Description: WebSocketConfig配置类* </p>** @author * @version * @create * @see */@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {registry.addHandler(new MyWebSocketHandler(), "/ws").setAllowedOrigins("*");
创建MyWebSocketHandler类

这段代码是一个WebSocket处理器中的消息处理方法,用来处理WebSocket客户端发送的消息

/*** <p>* Description: MyWebSocketHandler用 来处理WebSocket客户端发送的消息* </p>** @author * @version * @create * @see */
@Slf4j
public class MyWebSocketHandler implements WebSocketHandler {private static final Map<String, WebSocketSession> sessions = new ConcurrentHashMap<>();private static final Map<String, Set<String>> groups = new ConcurrentHashMap<>();@Overridepublic void afterConnectionEstablished(WebSocketSession session) throws Exception {sessions.put(session.getId(), session);}@Overridepublic void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {String payload = message.getPayload().toString();log.info("接收到的用户消息 {}", payload);JSONObject json = JSON.parseObject(payload);String type = json.getString("type");//  用户加入了群组if ("join".equals(type)) {String groupId = json.getString("groupId");groups.computeIfAbsent(groupId, k -> new HashSet<>()).add(session.getId());} else if ("leave".equals(type)) {String groupId = json.getString("groupId");groups.computeIfPresent(groupId, (k, v) -> {v.remove(session.getId());return v;});// 接收到了用户消息} else if ("message".equals(type)) {String groupId = json.getString("groupId");Set<String> groupSessions = groups.get(groupId);for (String sessionId : groupSessions) {WebSocketSession s = sessions.get(sessionId);if (s != null && s.isOpen()) {s.sendMessage(new TextMessage(payload));}}}}@Overridepublic void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {sessions.remove(session.getId());}@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {sessions.remove(session.getId());groups.values().forEach(v -> v.remove(session.getId()));}@Overridepublic boolean supportsPartialMessages() {return false;}
}
前端的html测试页面
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>WebSocket Chat</title>
</head>
<body><div id="output"></div><input id="input" type="text" placeholder="Type your message"><button id="send">Send</button><button id="join">Join Group</button><button id="leave">Leave Group</button><script>var socket = new WebSocket("ws://localhost:8080/ws");socket.onopen = function(event) {console.log("WebSocket connected");};socket.onmessage = function(event) {var message = event.data;var output = document.getElementById("output");var p = document.createElement("p");p.innerText = message;output.appendChild(p);};socket.onclose = function(event) {console.log("WebSocket disconnected");};var sendButton = document.getElementById("send");var input = document.getElementById("input");var joinButton = document.getElementById("join");var leaveButton = document.getElementById("leave");sendButton.addEventListener("click", function() {var message = {userId: "1",type: "message",groupId: "group1",content: input.value};socket.send(JSON.stringify(message));input.value = "";});joinButton.addEventListener("click", function() {var message = {userId: "1",type: "join",groupId: "group1"};socket.send(JSON.stringify(message));});leaveButton.addEventListener("click", function() {var message = {userId: "1",type: "leave",groupId: "group1"};socket.send(JSON.stringify(message));});socket.onmessage = function(event) {var message = event.data;var output = document.getElementById("output");var p = document.createElement("p");p.innerText = message;output.appendChild(p);
};</script>
</body>
</html>

这个WebSocket处理器实现了群聊功能,并支持用户加入和离开群组时向群组中的其他用户发送通知。

启动Spring Boot项目.点击加入群主,然后就可以发送消息了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/860215.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python爬取中国福彩网彩票数据并以图表形式显示

网页分析 首先打开中国福彩网&#xff0c;点击双色球&#xff0c;选择往期开奖栏目 进入栏目后&#xff0c;选定往期的奖金数目作为我们想要爬取的目标内容 明确目标后&#xff0c;开始寻找数据所在的位置 鼠标右击页面&#xff0c;打开网页源代码&#xff0c;在源代码中搜索…

vue3-openlayers 轨迹回放(历史轨迹)(ol-animation-path实现)

本篇介绍一下使用vue3-openlayers轨迹回放&#xff08;历史轨迹&#xff09;&#xff08;ol-animation-path实现&#xff09; 1 需求 轨迹回放&#xff08;历史轨迹&#xff09;实时轨迹 2 分析 轨迹回放&#xff08;历史轨迹&#xff09;&#xff0c;一般是一次性拿到所有…

功能测试【测试用例模板、Bug模板、手机App测试★】

功能测试 Day01 web项目环境与测试流程、业务流程测试一、【了解】web项目环境说明1.1 环境的定义&#xff1a;项目运行所需要的所有的软件和硬件组合1.2 环境(服务器)的组成&#xff1a;操作系统数据库web应用程序项目代码1.3 面试题&#xff1a;你们公司有几套环境&#xff1…

淘宝用户行为分析大数据可视化

文章目录 1. 项目概述2. 技术栈3. 目录结构4. 数据处理流程5. 前端部分5.1 HTML (index.html)5.2 CSS (layer.css)5.3 JavaScript (chart.js) 6. 后端部分7. 数据可视化7.1 ECharts 图表 8. 主要功能模块9. 代码解析10. 数据接口11. 项目功能描述12. 代码功能实现12.1 HTML (in…

udp传输协议,java,发送端和接收端

UDP&#xff08;用户数据报协议&#xff09;是一个无连接的、简单的传输层协议&#xff0c;它用于传输短消息服务&#xff08;SMS&#xff09;、实时应用&#xff08;如视频流、在线游戏&#xff09;以及其他对数据传输顺序和可靠性要求不高的场景。下面是UDP传输层的工作过程及…

Kubernetes 中 ElasticSearch 中的 MinIO 审核日志

无论您是在本地还是在云中&#xff0c;您都希望确保以同构的方式设置工具和流程。无论在何处访问基础结构&#xff0c;您都希望确保用于与各种基础结构进行交互的工具与其他区域相似。 考虑到这一点&#xff0c;在部署您自己的 MinIO 对象存储基础架构时&#xff0c;深入了解您…

无需 AU 专业工具,简单有效的人声分离操作图文教程来了

音乐制作与音频编辑已成为众多创意工作者不可或缺的一部分。无论是制作混音、进行音乐分析&#xff0c;还是为视频内容寻找完美的配音&#xff0c;人声分离技术都扮演着至关重要的角色。 传统上&#xff0c;这样的任务可能需要专业的音频编辑软件如 Adobe Audition&#xff08…

关闭Chrome浏览器的跨域限制

有安全问题的非工程师&#xff0c;还是不要弄了。我只试过macOS啊&#xff0c;其他的系统没有试过。就是为了开发的时候解决这个问题 Access to XMLHttpRequest at https://xxxx from origin http://127.0.0.1:3000 has been blocked by CORS policy: No Access-Control-Allow-…

【算法面试】在排序数组中查找元素的第一个和最后一个位置:详细题解

目录 题目描述 示例 示例 1&#xff1a; 示例 2&#xff1a; 示例 3&#xff1a; 问题分析 详细步骤 解决方法 方法 1&#xff1a;标准二分查找&#xff08;分开查找第一个和最后一个&#xff09; 方法 2&#xff1a;优化版二分查找&#xff08;合并查找逻辑&#xf…

热电发电机越来越受到研发关注

热电发电机 (TEG) 利用热量&#xff08;或更准确地说&#xff0c;温差&#xff09;和众所周知的塞贝克效应来发电。它们的应用范围从收集可用热能&#xff0c;尤其是在工业和其他情况下“浪费”的热能&#xff0c;到在放射性同位素热发电机 (RTG) 中使用航天器的放射性电源作为…

【docker】2. 编排容器技术发展史(了解)

该篇文章介绍的主要是编排以及容器技术的发展史(了解即可)&#xff0c;如果想单纯学习docker命令操作可直接略过&#xff01;&#xff01;&#xff01; 容器技术发展史 Jail 时代 容器不是一个新概念或者新技术&#xff0c;很早就有了&#xff0c;只是近几年遇到了云计算&am…

mac单机游戏推荐:帝国时代2 for Mac中文安装包

帝国时代2是一款经典的即时战略游戏&#xff0c;由微软游戏工作室开发。玩家可以选择从欧洲、亚洲或美洲的不同文明开始游戏&#xff0c;建立自己的帝国并与其他文明进行战争、贸易和外交。游戏中包含了丰富的历史背景和真实的历史事件&#xff0c;玩家需要策略性地管理资源、招…

【机器学习】ChatTTS:开源文本转语音(text-to-speech)大模型天花板

目录 一、引言 二、TTS&#xff08;text-to-speech&#xff09;模型原理 2.1 VITS 模型架构 2.2 VITS 模型训练 2.3 VITS 模型推理 三、ChatTTS 模型实战 3.1 ChatTTS 简介 3.2 ChatTTS 亮点 3.3 ChatTTS 数据集 3.4 ChatTTS 部署 3.4.1 创建conda环境 3.4.2 拉取源…

Java项目毕业设计:基于springboot+vue的幼儿园管理系统

数据库:MYSQL5.7 **应用服务:Tomcat7/Tomcat8 使用框架springbootvue** 项目介绍 管理员&#xff1b;首页、个人中心、用户管理、教师管理、幼儿信息管理、班级信息管理、工作日志管理、会议记录管理、待办事项管理、职工考核管理、请假信息管理、缴费信息管理、幼儿请假管理…

【漏洞复现】极限OA video_file.php 任意文件读取漏洞

免责声明&#xff1a; 本文内容旨在提供有关特定漏洞或安全漏洞的信息&#xff0c;以帮助用户更好地了解可能存在的风险。公布此类信息的目的在于促进网络安全意识和技术进步&#xff0c;并非出于任何恶意目的。阅读者应该明白&#xff0c;在利用本文提到的漏洞信息或进行相关测…

开源最强AI一键抠图一键去背景模型RMBG-1.4

目录 前言训练数据图像分布&#xff1a;定性评估 应用场景安装用法 前言 RMBG v1.4 是BRIA AI最先进的背景去除模型&#xff0c;旨在有效地将各种类别和图像类型的前景与背景分开。该模型已在精心选择的数据集上进行训练&#xff0c;其中包括&#xff1a;一般库存图片、电子商…

使用 scikit-learn进行简单回归分析

使用 scikit-learn&#xff08;简称 sklearn&#xff09;进行简单回归分析的教程。这里我们以波士顿房价数据集&#xff08;Boston House Prices dataset&#xff09;为例&#xff0c;介绍如何使用线性回归&#xff08;Linear Regression&#xff09;模型 环境准备 确保已经安…

疲劳驾驶智能识别摄像机

疲劳驾驶智能识别摄像机在道路安全管理中扮演着越来越重要的角色。这些先进的设备不仅仅是简单的监控工具&#xff0c;它们通过先进的技术和算法&#xff0c;有效地识别和预防司机疲劳驾驶&#xff0c;从而大大减少了交通事故的风险。 首先&#xff0c;这些智能识别摄像机采用高…

IP地址的数量限制

IP地址&#xff08;IPv4&#xff09;是一个4字节32位的正整数&#xff0c;因此一共有个IP地址&#xff0c;即将近43亿个IP地址。但TCP/IP协议规定&#xff0c;每个主机都要有一个IP地址 现在全世界人口已经有70多亿了&#xff0c;电脑、手机等都需要IP地址。随着科技的发展&am…

如何通过数据驱动的动态调度来优化pcdn的效率?

要通过数据驱动的动态调度来优化P2P内容分发网络&#xff08;PCDN&#xff09;的效率&#xff0c;可以采取以下几个关键步骤&#xff1a; 一&#xff0e;数据收集与分析 1.流量监控&#xff1a;收集PCDN网络中每个节点的流量数据&#xff0c;包括上传、下载、转发量等。 2.性…