20240603每日通信--------springboot使用netty-socketio集成即时通信WebSocket

简单效果图

群聊,私聊,广播都可以支持。
在这里插入图片描述

基础概念:

  • springboot
  • netty-socketio
  • WebSocket

POM文件:

 <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><artifactId>spring-boot-demo-websocket-socketio</artifactId><version>1.0.0-SNAPSHOT</version><packaging>jar</packaging><name>spring-boot-demo-websocket-socketio</name><description>Demo project for Spring Boot</description><parent><groupId>com.xkcoding</groupId><artifactId>spring-boot-demo</artifactId><version>1.0.0-SNAPSHOT</version></parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version><netty-socketio.version>1.7.16</netty-socketio.version></properties><dependencies><dependency><groupId>com.corundumstudio.socketio</groupId><artifactId>netty-socketio</artifactId><version>${netty-socketio.version}</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency></dependencies><build><finalName>spring-boot-demo-websocket-socketio</finalName><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

websocket服务器配置

/*** <p>* websocket服务器配置* </p>*/
@Configuration
@EnableConfigurationProperties({WsConfig.class})
public class ServerConfig {@Beanpublic SocketIOServer server(WsConfig wsConfig) {com.corundumstudio.socketio.Configuration config = new com.corundumstudio.socketio.Configuration();config.setHostname(wsConfig.getHost());config.setPort(wsConfig.getPort());//这个listener可以用来进行身份验证config.setAuthorizationListener(data -> {// http://localhost:8081?token=xxxxxxx// 例如果使用上面的链接进行connect,可以使用如下代码获取用户密码信息,本文不做身份验证String token = data.getSingleUrlParam("token");// 校验token的合法性,实际业务需要校验token是否过期等等,参考 spring-boot-demo-rbac-security 里的 JwtUtil// 如果认证不通过会返回一个 Socket.EVENT_CONNECT_ERROR 事件return StrUtil.isNotBlank(token);});return new SocketIOServer(config);}/*** Spring 扫描自定义注解*/@Beanpublic SpringAnnotationScanner springAnnotationScanner(SocketIOServer server) {return new SpringAnnotationScanner(server);}
}

核心事件处理类

/*** <p>* 消息事件处理* </p>*/
@Component
@Slf4j
public class MessageEventHandler {@Autowiredprivate SocketIOServer server;@Autowiredprivate DbTemplate dbTemplate;/*** 添加connect事件,当客户端发起连接时调用** @param client 客户端对象*/@OnConnectpublic void onConnect(SocketIOClient client) {if (client != null) {String token = client.getHandshakeData().getSingleUrlParam("token");// 模拟用户id 和token一致String userId = client.getHandshakeData().getSingleUrlParam("token");UUID sessionId = client.getSessionId();dbTemplate.save(userId, sessionId);log.info("连接成功,【token】= {},【sessionId】= {}", token, sessionId);} else {log.error("客户端为空");}}/*** 添加disconnect事件,客户端断开连接时调用,刷新客户端信息** @param client 客户端对象*/@OnDisconnectpublic void onDisconnect(SocketIOClient client) {if (client != null) {String token = client.getHandshakeData().getSingleUrlParam("token");// 模拟用户id 和token一致String userId = client.getHandshakeData().getSingleUrlParam("token");UUID sessionId = client.getSessionId();dbTemplate.deleteByUserId(userId);log.info("客户端断开连接,【token】= {},【sessionId】= {}", token, sessionId);client.disconnect();} else {log.error("客户端为空");}}/*** 加入群聊** @param client  客户端* @param request 请求* @param data    群聊*/@OnEvent(value = Event.JOIN)public void onJoinEvent(SocketIOClient client, AckRequest request, JoinRequest data) {log.info("用户:{} 已加入群聊:{}", data.getUserId(), data.getGroupId());client.joinRoom(data.getGroupId());server.getRoomOperations(data.getGroupId()).sendEvent(Event.JOIN, data);}@OnEvent(value = Event.CHAT)public void onChatEvent(SocketIOClient client, AckRequest request, SingleMessageRequest data) {Optional<UUID> toUser = dbTemplate.findByUserId(data.getToUid());if (toUser.isPresent()) {log.info("用户 {} 刚刚私信了用户 {}:{}", data.getFromUid(), data.getToUid(), data.getMessage());sendToSingle(toUser.get(), data);client.sendEvent(Event.CHAT_RECEIVED, "发送成功");} else {client.sendEvent(Event.CHAT_REFUSED, "发送失败,对方不想理你");}}@OnEvent(value = Event.GROUP)public void onGroupEvent(SocketIOClient client, AckRequest request, GroupMessageRequest data) {Collection<SocketIOClient> clients = server.getRoomOperations(data.getGroupId()).getClients();boolean inGroup = false;for (SocketIOClient socketIOClient : clients) {if (ObjectUtil.equal(socketIOClient.getSessionId(), client.getSessionId())) {inGroup = true;break;}}if (inGroup) {log.info("群号 {} 收到来自 {} 的群聊消息:{}", data.getGroupId(), data.getFromUid(), data.getMessage());sendToGroup(data);} else {request.sendAckData("请先加群!");}}/*** 单聊*/public void sendToSingle(UUID sessionId, SingleMessageRequest message) {server.getClient(sessionId).sendEvent(Event.CHAT, message);}/*** 广播*/public void sendToBroadcast(BroadcastMessageRequest message) {log.info("系统紧急广播一条通知:{}", message.getMessage());for (UUID clientId : dbTemplate.findAll()) {if (server.getClient(clientId) == null) {continue;}server.getClient(clientId).sendEvent(Event.BROADCAST, message);}}/*** 群聊*/public void sendToGroup(GroupMessageRequest message) {server.getRoomOperations(message.getGroupId()).sendEvent(Event.GROUP, message);}
}

websocket 服务器启动类

/*** <p>* websocket服务器启动* </p>** @author yangkai.shen* @date Created in 2018-12-18 17:07*/
@Component
@Slf4j
public class ServerRunner implements CommandLineRunner {@Autowiredprivate SocketIOServer server;@Overridepublic void run(String... args) {server.start();log.info("websocket 服务器启动成功。。。");}
}

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

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

相关文章

【leetcode10-21】子串、普通数组、矩阵

子串 560.和为K的子数组【没理解】 什么是前缀和&#xff1a;前缀和指一个数组的某下标之前的所有数组元素的和&#xff08;包含其自身&#xff09; 通常&#xff0c;会在前缀和首位放一个0。比如数组[1,2,3。其前缀和是[0,1,3,6] 前缀和通常可以帮助我们快速计算某个区间内的…

一些智能音箱类的软硬件方案

主要参考资料 Rabbit R1: https://www.rabbit.tech/rabbit-r1 mediatek-helio-p35: https://www.mediatek.com/products/smartphones-2/mediatek-helio-p35 NSdisplay: https://www.nsdisplay.com/ai-holobox-mini/ai-holobox-mini.html RK3566: https://www.rock-chips.com/a/…

常用技巧-PPT时你真的做对了吗?

常用技巧-PPT时你真的做对了吗&#xff1f; PPT时通常会通过多种表现手法将信息转化为图表&#xff0c;更好的凸显自己的专业素养。将数据转化为图表是对的&#xff0c;那么你真的用对了图表了吗&#xff1f; 话不多说&#xff0c;直接上干货&#xff1a; 时间线图 时间线是…

AI网络爬虫:对网页指定区域批量截图

对网页指定区域批量截图&#xff0c;可以在deepseek的代码助手中输入提示词&#xff1a; 你是一个Python编程专家&#xff0c;一步一步的思考&#xff0c;完成一个对网页指定区域截图的python脚本的任务&#xff0c;具体步骤如下&#xff1a; 设置User-Agent: Mozilla/5.0 (…

基于深度学习的CT影像肺癌检测识别

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长 QQ 名片 :) 1. 项目简介 肺癌是全球范围内导致癌症死亡的主要原因之一&#xff0c;早期检测和诊断对于提高患者生存率至关重要。随着深度学习技术的迅猛发展&#xff0c;基于CT影像的肺癌检测识别成为了研究热点。本文介绍…

线段交点检测:扫描线算法

NSDT工具推荐&#xff1a; Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 - REVIT导出3D模型插件 - 3D模型语义搜索引擎 - Three.js虚拟轴心开发包 - 3D模型在线减面 - STL模型在线切割 几何对象的相交检测是计算…

ChatGPT Edu版本来啦:支持GPT-4o、自定义GPT、数据分析等

5月31日&#xff0c;OpenAI在官网宣布&#xff0c;推出ChatGPT Edu版本。 据悉&#xff0c;这是一个专门为大学校园提供的ChatGTP&#xff0c;支持GPT-4o、网络搜索、自定义GPT、数据分析、代码生成等功能&#xff0c;可以极大提升学生、老师的学习质量和教学效率。 目前&…

【UE5教程】使用蓝图显示鼠标

首先&#xff0c;在您的项目中创建一个新的蓝图类&#xff0c;继承自PlayerController。在蓝图编辑器中&#xff0c;找到Event BeginPlay节点&#xff0c;并从它引出一条线。添加Set Show Mouse Cursor节点&#xff0c;勾选Visible&#xff0c;以确保鼠标在游戏开始时可见。 鼠…

python-web应用程序-Django数据库

python-web应用程序-Django数据库-操作表 原始方法&#xff1a; import pymysql#1.链接mysql conn pymysql.connect(host127.0.0.1,port 2206,user root,passwd root123,charset utf8,db unicom) cursor conn.cursor(cursor pymysql.cursors.DictCursor)#2.发送指令 …

1.4 Unicode简介

现在的Windows操作系统有许多不同语言版本&#xff0c;可以支持所有国家现有的语言文字。这就涉及到不同字符集的编码规则。 本节必须掌握的知识点&#xff1a; 字符集 C语言款字符 宽字符和Windows 1.4.1 字符集 ■ANSI多字节字符集 ●ASCII码 现代计算机发源于美国&…

云原生架构案例分析_3.某快递公司核心业务系统云原生改造

名称解释&#xff1a; 阿里云ACK&#xff1a;阿里云容器服务 Kubernetes 版 ACK&#xff08;Container Service for Kubernetes&#xff09;集成Kubernetes网络、阿里云VPC、阿里云SLB&#xff0c;提供稳定高性能的容器网络。本文介绍ACK集群网络及阿里云网络底层基础设施的重要…

[Algorithm][动态规划][回文串问题][回文子串][最长回文子串][分割回文串Ⅳ]详细讲解

目录 0.原理讲解1.回文子串1.题目链接2.算法原理详解3.代码实现 2.最长回文子串1.题目链接3.代码实现 3.分割回文串 IV1.题目链接2.算法原理详解3.代码实现 0.原理讲解 动态规划能够将所有的子串是否是回文的信息&#xff0c;保存在dp表里面状态表示一般经验&#xff1a;以[i,…

Harmony开发 List/Scroll 组件最后一个item显示不全或布局显示不完整

今天在做Harmony开发的时候遇到一个问题,List组件的最后一个item显示不全&#xff0c;如下图&#xff0c;item-9显示不出来&#xff0c;显示了一部分 这个页面的代码结构如下&#xff1a; Column() {Row() {Text(文本1).fontSize(15).fontColor(Color.Black)Text(文本2).font…

基于Vue3的Uniapp实训项目|一家鲜花店

基于Vue的Uniapp实训指导项目 项目预览&#xff1a; 在这里插入图片描述 pages.json {"pages": [ //pages数组中第一项表示应用启动页&#xff0c;参考&#xff1a;https://uniapp.dcloud.io/collocation/pages{"path": "pages/index/index",&…

群体优化算法---蜂群优化算法应用于数据挖掘

介绍 蜂群优化算法&#xff08;Bee Algorithm, BA&#xff09;及其变种主要模拟蜜蜂的觅食行为&#xff0c;以解决复杂的优化问题。这类算法通过蜜蜂之间的信息交流和协作来探索解空间&#xff0c;寻找全局最优解。主要应用于参数优化&#xff0c;结构优化&#xff0c;机器学习…

The First项目报告:去中心化知识产权治理协议MON Protocol如何革新链游产业?

2023年12月&#xff0c;RPG NFT 游戏 Pixelmon 首席执行官 GiulioX 在 X 平台表示&#xff0c;确认将推出代币 MON&#xff0c;代币生成&#xff08;TGE&#xff09;时间将取决于 MON 的路线图和主流 CEX 的启动板队列。12 月 11 日&#xff0c;RPG NFT 游戏 Pixelmon 首席执行…

element-plus的Layout组件

elment-plus的layout组件包括el-row和e-col&#xff0c;和bootstrap的栅格类似&#xff0c;e-row采用flex布局&#xff0c;分成了24个栅栏&#xff0c;单个e-col默认占24,可以通过span属性指定其大小&#xff0c;offset属性指定其偏移的栅栏个数。e-row组件的父组件不要使用dis…

深度学习(三)

5.Functional API 搭建神经网络模型 5.1利用Functional API编写宽深神经网络模型进行手写数字识别 import numpy as npimport pandas as pdimport matplotlib.pyplot as pltfrom sklearn.datasets import load_irisfrom sklearn.model_selection import train_test_splitfrom…

Stable diffusion文生图大模型——隐扩散模型原理解析

1、前言 本篇文章&#xff0c;我们将讲这些年非常流行的文生图大模型——Stable Diffusion。该模型也不难&#xff0c;甚至说很简单。创新点也相对较少&#xff0c;如果你学会了我以前的文章讲过的模型&#xff0c;学习这个也自然水到渠成&#xff01; 参考论文&#xff1a;H…

腾讯云 TDMQ for Apache Pulsar 多地区高可用容灾实践

作者介绍 林宇强 腾讯云高级工程师 专注于消息队列、API网关、微服务、数据同步等 PaaS 领域。有多年的开发和维护经验&#xff0c;目前在腾讯云从事 TDMQ Pulsar 商业化产品方向的研发工作。 导语 本文将从四个维度&#xff0c;深入剖析 Pulsar 在多可用区高可用领域的容…