Java21 + SpringBoot3集成WebSocket

文章目录

    • 前言
    • 相关技术简介
      • 什么是WebSocket
      • WebSocket的原理
      • WebSocket与HTTP协议的关系
      • WebSocket优点
      • WebSocket应用场景
    • 实现方式
      • 1. 添加maven依赖
      • 2. 添加WebSocket配置类,定义ServerEndpointExporter Bean
      • 3. 定义WebSocket Endpoint
      • 4. 前端创建WebSocket对象
    • 总结

前言

近日心血来潮想做一个开源项目,目标是做一款可以适配多端、功能完备的模板工程,包含后台管理系统和前台系统,开发者基于此项目进行裁剪和扩展来完成自己的功能开发。
本项目为前后端分离开发,后端基于Java21SpringBoot3开发,前端提供了vue、angular、react、uniapp、微信小程序等多种脚手架工程。
本文主要介绍项目中如何集成WebSocket实现服务器端与客户端的双向通信。

相关技术简介

什么是WebSocket

WebSocket 是一种网络通信协议。RFC6455 定义了它的通信标准。
http是一种无状态,无连接,单向的应用层协议,它采用了请求/响应模型,通信请求只能由客户端发起,服务端对请求做出应答处理。这样的弊端显然是很大的,只要服务端状态连续变化,客户端就必须实时响应,都是通过javascript与ajax进行轮询,这样显然是非常麻烦的,同时轮询的效率低,非常的浪费资源(http一直打开,一直重复的连接)。
于是就有了WebSocket,它是一种全面双工通讯的网络技术,任意一方都可以建立连接将数据推向另一方,WebSocket只需要建立一次连接,就可以一直保持。

WebSocket的原理

  1. WebSocket约定了一个通信的规范,通过一个握手的机制,客户端和服务器之间能建立一个类似tcp的连接,从而方便它们之间的通信
  2. 在WebSocket出现之前,web交互一般是基于http协议的短连接或者长连接
  3. WebSocket是一种全新的协议,不属于http无状态协议,协议名为"ws"

WebSocket与HTTP协议的关系

WebSocket优点

  1. 减少请求费时费资源:是真正的全双工方式,建立连接后,服务器与客户端时完全对等的,可以相互请求,减少了不必要的网络请求时间损耗和网络流量;
  2. 更持久:WebSocket协议通过第一个request建立TCP连接后,只要不主动关闭,就能一直保持连接状态交换数据;
  3. 服务端可以主动向客户端发送消息;

WebSocket应用场景

社交聊天、弹幕、多玩家游戏、协同编辑、股票基金实时报价、体育实况更新、视频会议/聊天、基于位置的应用、在线教育、智能家居等需要高实时的场景都可以使用WebSocket技术实现。

实现方式

本项目后端基于Java 21SpringBoot3开发,前端基于Vue3实现。

1. 添加maven依赖

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

2. 添加WebSocket配置类,定义ServerEndpointExporter Bean

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

3. 定义WebSocket Endpoint

/*** 消息提醒计数WebSocket*/
@ServerEndpoint("/ws/test/{userId}")
@Component
@Slf4j
public class TestWebSocketServer {/*** 与某个客户端的连接会话,需要通过它来给客户端发送数据*/private Session session;/*** 用户ID*/private Long userId;/*** concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。* 虽然@Component默认是单例模式的,但springboot还是会为每个websocket连接初始化一个bean,所以可以用一个静态set保存起来。*/private static final CopyOnWriteArraySet<MessageCountWebSocketServer> webSockets = new CopyOnWriteArraySet<>();/*** 用来存在线连接用户信息*/private static final ConcurrentHashMap<Long, Session> sessionPool = new ConcurrentHashMap<>();/*** 链接成功调用的方法*/@OnOpenpublic void onOpen(Session session, @PathParam(value = "userId") Long userId) {this.session = session;this.userId = userId;webSockets.add(this);sessionPool.put(userId, session);log.info("建立与UserID:{}的消息提醒计数连接", userId);}/*** 链接关闭调用的方法*/@OnClosepublic void onClose() {webSockets.remove(this);sessionPool.remove(this.userId);log.info("关闭与UserID:{}的消息提醒计数连接", userId);}/*** 收到客户端消息后调用的方法*/@OnMessagepublic void onMessage(String message) {log.info("接收到UserID:{}的消息{}", userId, message);}/*** 发送错误时的处理*/@OnErrorpublic void onError(Session session, Throwable error) {log.error("发送到UserID:{}的消息传输失败", userId, error);}/*** 广播消息** @param message*/public void sendAllMessage(String message) {for (MessageCountWebSocketServer socketServer : webSockets) {if (socketServer.session.isOpen()) {socketServer.session.getAsyncRemote().sendText(message);}}}/*** 单人单播消息** @param userId* @param message*/public void sendOneMessage(Long userId, String message) {Session session = sessionPool.get(userId);if (session != null && session.isOpen()) {session.getAsyncRemote().sendText(message);}}/*** 多人单播消息** @param userIds* @param message*/public void sendMoreMessage(Long[] userIds, String message) {for (Long userId : userIds) {Session session = sessionPool.get(userId);if (session != null && session.isOpen()) {session.getAsyncRemote().sendText(message);}}}
}

4. 前端创建WebSocket对象

以下代码基于Vue3的组合式API编写。

<script setup>import { onMounted, onBeforeMount } from 'vue';/*** @type {WebSocket}*/let websocket = null;onMounted(async () => {initTestWebSocket();});onBeforeMount(async()=>{websocket && websocket.close();});const initTestWebSocket = async () => {const userId = '当前用户ID';console.log("尝试建立websockect连接");websocket = new WebSocket(`/ws/test/${userId}`);websocket.onopen = function (event) {console.log("建立连接");}websocket.onclose = function (event) {console.log('连接关闭')//尝试重连websocketreconnectMessageWebSocket();}//建立通信后,监听到后端的数据传递websocket.onmessage = function (event) {// 打印后端传来的数据console.log(event.data);// 调用WebSocket对象的send方法可向后端发送数据// websocket.send("test data");}websocket.onerror = function () {console.log("数据发送失败");}// 窗口关闭前关闭WebSocket连接window.onbeforeunload = function () {websocket.close();}};// 重连const reconnectMessageWebSocket = () => {console.log("正在重连");// 进行重连setTimeout(() => {initTestWebSocket();}, 1000);}
</script>

总结

本文介绍了WebSocket的相关概念,以及如何基于Java21、SpringBoot3和Vue3使用WebSocket,在使用过程中也遇到了一些问题。

  • 执行mvn packagemvn test命令时报错

    请参阅 Java21 + SpringBoot3使用spring-websocket时执行mvn package报错。

  • 如果后端使用Spring SecurityShiroSa-Token等技术,需要考虑使用@ServerEndpoint注解所配置url的权限控制问题。

我也会及时的更新后续实践中所遇到的问题,希望与诸位看官一起进步。
如有错误,还望批评指正。

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

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

相关文章

【Nacos】Nacos 双端版本升级实战手册

背景 由于原来使用的 Nacos 版本&#xff08;1.1.4&#xff09;存在安全漏洞&#xff0c;需要进行升级修复。经过查询后&#xff0c;决定将版本升级到2.2.4。 Nacos 服务共有三个&#xff1a; 192.168.2.190:8848192.168.2.191:8848192.168.2.192:8848 步骤 服务端升级&am…

[Kubernetes]9. K8s ingress讲解借助ingress配置http,https访问k8s集群应用

前面讲解了使用Helm部署mysql集群,这里来看看使用Ingress搭建负载均衡功能 1.介绍 功能类似 Nginx ,可以根据域名、路径把请求转发到不同的 Service , Ingress 为外部访问集群提供了一个 统一 入口, 避免 了 对外暴露集群端口 ,可以配置 https,http访问集群应用,接下来看看如…

2024年《一个项目征服Java中高级体系》博客计划

终于下决心来写一套大型的Java 笔记&#xff0c;不为别的&#xff0c;就是为了强迫自己将整个Java体系梳理清楚&#xff0c;让自己成为内功扎实的Java高级架构师。牛已经吹出来了&#xff0c;不做对不起网友&#xff01; 经过一个多月的持续规划&#xff0c;现在终于定好了整体…

8年老鸟,自动化测试经验,测试数据管理分析总结,一篇打通...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 问题&#xff1a;…

Linux学习记录——사십삼 高级IO(4)--- Epoll型服务器

文章目录 1、理解Epoll和对应接口2、实现 1、理解Epoll和对应接口 poll依然需要OS去遍历所有fd。一个进程去多个特定的文件中等待&#xff0c;只要有一个就绪&#xff0c;就使用select/poll系统调用&#xff0c;让操作系统把所有文件遍历一遍&#xff0c;哪些就绪就加上哪些fd…

ssm基于VUE.js的在线教育系统论文

摘 要 随着学习压力越来越大&#xff0c;课外参加补习班的学生越来越多。现在大多数学生采用请家教、自学、报名补习班的方式进行课外的额外学习。请家教费用昂贵&#xff0c;自学效率低&#xff0c;碰到自己不会的知识不能及时得到解达&#xff0c;报名补习班需要时间、地点的…

x-cmd pkg | trash-cli - 类 Unix 系统的命令行垃圾桶

目录 简介首次用户技术特点竞品和相关作品进一步阅读 简介 trash-cli 是类 Unix 系统的命令行垃圾桶&#xff0c;用于移动文件到回收站&#xff0c;同时会记录文件的原地址和删除日期。 该工具使用与 GNOME、KDE ​​和 XFCE 等桌面环境相同的垃圾桶&#xff0c;所以即使是非 …

PVE虚拟机配置文件恢复

一、pve 创建的虚拟机的配置文件位置 在宿主机的 /etc/pve/qemu-server&#xff0c;这里有创建虚拟机的相关硬件信息。 rootpve1:/etc/pve/qemu-server# pwd /etc/pve/qemu-server二、故障现象 在命令行执行qm list不显示虚拟机&#xff0c;查看 宿主机的 /etc/pve/qemu-ser…

Codeforces Round 913 (Div. 3)E 不进位各数位和与打表

Problem - E - Codeforces digsum(a)digsum(b)digsum(c)digsum(n) 要点一&#xff1a; 当左边和发生进位&#xff0c;比如56 11&#xff0c;那么数位和会变小。其实下一位就是相加后对9取余&#xff0c;各数位和必定变小的。 要点二&#xff1a; 然后就是组合情况了&#x…

Echarts可视化-数据请求-代码实现和思路

需求&#xff1a;为前端可视化图表提供数据支持。 实现&#xff1a; 时间戳获取优化&#xff08;细化到秒&#xff09; 根据时间获取数据&#xff08;SQL编写&#xff09; 前端需求数据返回&#xff08;数据VO&#xff09; 内容 Apache ECharts 营业额统计 用户统计 订单…

搜维尔科技:【简报】元宇宙数字人赛道,《全息影像技术应用》!

期待着看展的主角来到今天要参观的全息影像展&#xff0c;平时就喜欢看展的她对于所谓的全息影像非常好奇&#xff0c;于是她带着期待的心情进入展内。进入展内的主角看到的是与之前完全不同的画展&#xff0c;每幅画看起来就像真的一样&#xff0c;充满好奇的她在展览的各处游…

【ONE·MySQL || 复合查询】

总言 主要内容&#xff1a;主要介绍一些复杂的查询&#xff0c;涉及多表查询、交叉连接、内连接、外连接、子查询、合并查询等。       文章目录 总言1、基本查询回顾1.0、博文说明1.1、一些例题1.1.1、查询工资高于500或岗位为MANAGER的雇员&#xff0c;同时还要满足他们的…

Python爬虫|使用urllib获取百度首页源码

在这个博客中&#xff0c;我们将一起探索百度首页的源码&#xff0c;深入了解从URL请求到页面呈现的全过程。我们将使用Python的urllib.request库来模拟浏览器发送请求&#xff0c;并解码响应中的页面源码。通过分析源码&#xff0c;我们将揭示网页的结构、内容和背后的工作原理…

【Redis】AOF 源码

在上篇, 我们已经从使用 / 机制 / AOF 过程中涉及的辅助功能等方面简单了解了 Redis AOF。 这篇将从源码的形式, 进行深入的了解。 1 Redis 整个 AOF 主要功能 Redis 的 AOF 功能概括起来就 2 个功能 AOF 同步: 将客户端发送的变更命令, 保存到 AOF 文件中AOF 重写: 随着 Red…

电脑重置网络后连不上网了怎么办

一般电脑重置网络后都会自动重新下载好网络配置&#xff0c;但是不免会出现一些意外&#xff0c;接下来就我遇到的重置后无法联网的解决方案 做一个分享&#xff1a; 1、按下“winR”打开运行输入 services.msc 。 2、找到 WLAN AutoConfig 和 Wired AutoConfig 服务&#xff…

如何安装Python

Python是一种流行的编程语言&#xff0c;拥有广泛的应用领域。为了开始使用Python&#xff0c;首先需要在计算机上安装Python解释器。在本文中&#xff0c;我们将介绍如何安装Python以及一些常见的安装步骤。 1. 下载Python 首先&#xff0c;你需要前往Python官方网站&#xf…

第 9 章 哈希表

文章目录 9.1 哈希表(散列)-Google 上机题9.2 哈希表的基本介绍9.3 google 公司的一个上机题: 9.1 哈希表(散列)-Google 上机题 看一个实际需求&#xff0c;google 公司的一个上机题:有一个公司,当有新的员工来报道时,要求将该员工的信息加入(id,性别,年龄,住址…),当输入该员…

软件测试|PyQt5实战教程(一)安装与环境配置

简介 我们之前介绍过使用tkinter创建图形用户界面&#xff08;GUI&#xff09;应用程序&#xff0c;现在我们来介绍另外一个用于创建GUI的神器——pyQt5&#xff0c;它可以用于创建跨平台的桌面应用程序。PyQt5 实现了一个 Python模块集&#xff0c;有 620 个类&#xff0c;60…

乐意购项目前端开发 #1

一、创建vue项目 1. vue create 项目名 2. 运行项目 npm install npm run dev3.使用Git管理项目 创建远程仓库 leyigou 在项目文件终端执行以下代码 git init # git 初始化#这个要使用自己的仓库 git remote add origin gitgitee.com:xie-weijia/leyigou.git # 添加远程仓…

[Docker] 基本名词

镜像(iamge)&#xff1a; Docker 镜像就好比是一个模板&#xff0c;可以通过这个模板来创建容器服务&#xff0c; 容器&#xff08;container&#xff09;: Docker利用容器技术&#xff0c;独立运行一个或则多个应用&#xff0c;通过镜像来创建的。 启动&#xff0c;停止&a…