从零开始的使用SpringBoot和WebSocket打造实时共享文本应用

在现代应用中,实时协作已经成为了非常重要的功能,尤其是在文档编辑、聊天系统和在线编程等场景中。通过实时共享文档,多个用户可以同时对同一份文档进行编辑,并能看到其他人的编辑内容。这种功能广泛应用于 Google Docs、Notion 等产品中。

在本文中,我们将实现一个简单的共享文本框,使用 WebSocket 技术来实现多人实时编辑同一份文本。通过 WebSocket 协议,客户端和服务器可以保持一个持续的连接,使得文档的内容能够实时同步到所有参与者。
(引流:https://juejin.cn/post/7445187277558628387)
效果图如下:

tutieshi_640x272_3s

1. 什么是 WebSocket?

WebSocket 是一种网络协议,它提供了一个全双工的通信通道,允许客户端和服务器之间进行实时、双向的数据传输。与传统的 HTTP 协议不同,WebSocket 连接在建立后会保持打开状态,不需要频繁的建立连接,从而大大提高了数据交换的效率。

WebSocket 协议通常用于实时聊天、在线游戏、金融行情推送等场景。在本文中,我们将利用 WebSocket 来实现一个共享文本框。

2. 项目需求

我们的目标是实现一个简单的共享文本框功能,要求如下:

  • 多个用户可以同时连接到同一个文档并进行编辑。
  • 每次用户编辑文本时,修改内容会即时同步到其他用户的浏览器。
  • 实现基本的文本框功能,包括输入和显示。

3. 技术栈

  • 前端:HTML、CSS、JavaScript(使用 WebSocket API)
  • 后端:SpringBoot
  • 通信协议:WebSocket

4. 实现步骤

4.1 搭建 WebSocket 服务端

首先,我们需要创建一个 WebSocket 服务器来处理客户端连接。具体步骤如下:

  1. 是maven依赖中引入websocket的依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
  1. 对WebSocket进行一些配置
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;/*** @ Description: 开启WebSocket支持* 用于在Spring框架的应用中配置和启用WebSocket功能。* 通过相关注解和方法的定义,使得应用能够正确地处理WebSocket连接和通信。*/
@Configuration
public class WebSocketConfig {//Bean生命周期的初始化// 用于将方法返回的ServerEndpointExporter对象作为一个Bean注册到Spring的容器中@Beanpublic ServerEndpointExporter serverEndpointExporter() {//创建并返回一个ServerEndpointExporter对象。// ServerEndpointExporter主要作用是扫描带有@ServerEndpoint注解的WebSocket端点类,并将它们注册到Servlet容器中,// 从而使得应用能够正确地处理WebSocket连接请求,实现WebSocket的通信功能。return new ServerEndpointExporter();}
}
  1. WebSocket服务器实现
import com.fasterxml.jackson.core.JsonProcessingException;
import org.springframework.stereotype.Service;import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;@Service
@ServerEndpoint("/api/websocket/sharedText/{sid}")
public class WebSocketServer {// 每个连接的 Sessionprivate Session session;private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<>();private static int onlineCount = 0;// 存储每个连接的 sidprivate String sid = "";// 存储每个连接的内容private static String content = "";@OnOpenpublic void onOpen(Session session, @PathParam("sid") String sid) {this.session = session;// 使用 URL 中的 sid 参数为当前连接设置 sidthis.sid = sid;webSocketSet.add(this); // 将当前连接添加到 WebSocket 客户端集合中addOnlineCount(); // 增加在线连接数try {sendMessage(this.content); // 向当前客户端发送连接成功消息System.out.println("有新窗口开始监听:" + sid + ", 当前在线人数为:" + getOnlineCount());} catch (IOException e) {System.out.println("websocket IO Exception");}}@OnClosepublic void onClose() {webSocketSet.remove(this); // 从 WebSocket 客户端集合中移除当前连接subOnlineCount(); // 减少在线连接数System.out.println("释放的 sid 为:" + sid);System.out.println("有一连接关闭!当前在线人数为 " + getOnlineCount());}@OnMessagepublic void onMessage(String message, Session session) throws JsonProcessingException {this.content = message;// 打印来自某个 sid 的消息内容System.out.println("收到来自窗口 " + sid + " 的信息: " + message);// 群发消息给所有已连接的客户端for (WebSocketServer item : webSocketSet) {try {item.sendMessage(message); // 向所有连接的客户端广播消息} catch (IOException e) {e.printStackTrace();}}}@OnErrorpublic void onError(Session session, Throwable error) {System.out.println("发生错误");error.printStackTrace();}// 向客户端发送消息public void sendMessage(String message) throws IOException {if (this.session != null && this.session.isOpen()) {this.session.getBasicRemote().sendText(message); // 发送消息}}public static synchronized int getOnlineCount() {return onlineCount;}public static synchronized void addOnlineCount() {WebSocketServer.onlineCount++;}public static synchronized void subOnlineCount() {WebSocketServer.onlineCount--;}public static CopyOnWriteArraySet<WebSocketServer> getWebSocketSet() {return webSocketSet;}
}

上述代码中,我们创建了一个 WebSocket 服务器并监听了 8080 端口。当有客户端连接时,服务器会触发 connection 事件,处理来自客户端的消息并将其广播给所有已连接的客户端。

4.2 创建前端页面

接下来,我们需要创建一个前端页面,用户可以在其中输入文本并实时看到其他用户的编辑内容。我们将使用 WebSocket API 与后端建立连接。

<!DOCTYPE html>
<html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>实时共享文本框 - WebSocket 实现</title><script src="https://code.jquery.com/jquery-3.1.1.min.js"></script><style>body {font-family: Arial, sans-serif;background-color: #f4f4f9;padding: 20px;display: flex;flex-direction: column;align-items: center;}h2 {margin-bottom: 20px;}#textBox {width: 80%;max-width: 900px;height: 300px;padding: 10px;font-size: 16px;border: 1px solid #ddd;border-radius: 5px;background-color: #fff;resize: none;box-sizing: border-box;}#message {margin-top: 20px;padding: 10px;width: 80%;max-width: 900px;border: 1px solid #ddd;border-radius: 5px;background-color: #fafafa;font-size: 14px;color: #555;}#message span {font-weight: bold;}.status {margin: 10px 0;color: #333;}.error {color: red;}.success {color: green;}.info {color: #555;}</style>
</head><body>
<h2>实时共享文本框</h2>
<textarea id="textBox" rows="20" cols="80" placeholder="开始编辑文本..."></textarea><br /><script type="text/javascript">let websocket = null;const sid = "100"; // 这里可以更改为动态获取的 sid,例如通过 URL 获取// 判断浏览器是否支持 WebSocketif ('WebSocket' in window) {websocket = new WebSocket(`ws://192.168.113.45:8080/api/websocket/sharedText/${sid}`);} else {alert('当前浏览器不支持 WebSocket');}// 连接错误时处理websocket.onerror = () => {updateStatus('WebSocket连接发生错误', 'error');};// 连接成功时处理websocket.onopen = () => {updateStatus('WebSocket连接成功', 'success');};// 接收消息时处理websocket.onmessage = (event) => {console.log(event);updateTextBox(event.data);};// 连接关闭时处理websocket.onclose = () => {updateStatus('WebSocket连接关闭', 'info');};// 窗口关闭时确保关闭 WebSocket 连接window.onbeforeunload = () => {closeWebSocket();};// 更新状态消息function updateStatus(message, type) {const statusDiv = document.getElementById('message');statusDiv.innerHTML = `<span class="${type}">${message}</span>`;}// 关闭 WebSocket 连接function closeWebSocket() {if (websocket) {websocket.close();}}// 监听文本框输入事件document.getElementById('textBox').addEventListener('input', function () {const message = this.value;if (message !== previousMessage) {websocket.send(message); // 发送消息到 WebSocketpreviousMessage = message; // 更新当前文本}});let previousMessage = ''; // 用于记录文本框内容,避免重复发送// 更新文本框内容function updateTextBox(content) {// 防止不停地将同一内容发送给其他用户if (document.getElementById('textBox').value !== content) {document.getElementById('textBox').value = content;}}
</script>
</body></html>

在前端页面中,我们创建了一个简单的文本框 (<textarea>) 供用户输入文本。当用户在文本框中输入内容时,input 事件会触发,内容会通过 WebSocket 发送给服务器。服务器收到消息后,会将其广播给所有其他连接的客户端,客户端接收到广播消息后会更新自己的文本框内容。

4.3 测试与运行

直接启动SpringBoot服务即可,同时打开web网页。

最终效果如下:

在一个网页端编辑,另一个网页端能及时收到变更。

5. 小结

通过这篇博客,我们实现了一个简单的实时共享文本框,利用 WebSocket 技术来实现多人实时编辑同一份文本。每当一个用户编辑文本时,服务器会将该编辑广播给其他在线用户,从而实现实时同步。这是一个基本的多人协作编辑功能,适用于在线文档编辑、聊天系统等场景。

在实际应用中,我们可以根据需求扩展更多功能,例如用户身份管理、权限控制、文本格式化、撤销/重做功能等。通过 WebSocket,我们不仅可以实现实时通信,还能为用户提供流畅的协作体验。在开发中,WebSocket 仍然是一个非常强大的工具,适用于许多实时协作的场景。

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

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

相关文章

【opencv入门教程】1.vs2017 + cmake 编译Opencv4.8.1 Sample

文章选自&#xff1a; 【一.准备工作】 1.opencv: https://opencv.org/releases/ 2.cmake &#xff1a;https://cmake.org/download/ 【二.编译配置】 1.解压下载后的opencv压缩包 2.打开cmake&#xff0c;将opencv sample路径及自定义的文件夹路径填入其中 3.按照1&…

五天SpringCloud计划——DAY3之服务治理(Nacos+OpenFeign+OKHttp)

一、引言 在微服务架构中&#xff0c;一个项目通常会被分为多个模块来降低耦合&#xff0c;但是通常情况下&#xff0c;一个项目中总会出现一种情况——一个模块内的方法需要调用另一个模块内的方法。本文就来使用NacosOpenFeignOKHttp帮助大家解决这个问题。 二、Nacos的使用…

leetcode 二进制数转字符串

1.题目要求: 2.题目代码: class Solution { public:string printBin(double num) {string result;double compare_value 1.0;//先给把0和.赋值给result;result.push_back(0);result.push_back(.);while(result.size() < 33){//利用十进制转换成二进制的方法//1.先给num …

软件项目标书参考,合同拟制,开发合同制定,开发协议,标书整体技术方案,实施方案,通用套用方案,业务流程,技术架构,数据库架构全资料下载(原件)

1、终止合同协议书 2、项目合作协议 3、合同交底纪要 4、合同管理台账 软件资料清单列表部分文档清单&#xff1a;工作安排任务书&#xff0c;可行性分析报告&#xff0c;立项申请审批表&#xff0c;产品需求规格说明书&#xff0c;需求调研计划&#xff0c;用户需求调查单&…

PADS系列:绘制RTL8306原理图的过程

大家好&#xff0c;我是山羊君Goat。 在所有相关的元件都被创建到了原理图库之后&#xff0c;就可以正式开始原理图的绘制了。不过绘制过程中也是会按照一定的顺序来进行的&#xff0c;这样可以达到事半功倍的效果。 首先就是主芯片的放置&#xff0c;这里有三个主芯片&#x…

c++:多态性

c三大特性&#xff1a;封装、继承、多态&#xff0c;其实这三者是相互联系的&#xff0c;相互包含的 1.概念 1.1编译时多态性&#xff08;静态多态性&#xff09; 主要通过函数重载和运算符重载来实现在编译时&#xff0c;编译器根据函数调用的参数类型或运算符的操作数类型来…

(ICML-2024)DoRA:权重分解低秩自适应

DoRA&#xff1a;权重分解低秩自适应 Paper是英伟达发表在ICML 2024的工作 Paper Title&#xff1a;DoRA: Weight-Decomposed Low-Rank Adaptation Code&#xff1a; 地址 Abstract 在广泛使用的参数高效微调 (PEFT) 方法中&#xff0c;LoRA 及其变体因避免了额外的推理成本而…

微信小程序从后端获取的图片,展示的时候上下没有完全拼接,有缝隙【已解决】

文章目录 1、index.wxml2、index.js3、detail.detail为什么 .rich-text-style 样式可以生效&#xff1f;1. <rich-text> 组件的特殊性2. 类选择器的作用范围3. 样式优先级4. line-height: 0 的作用5. 为什么直接使用 rich-text 选择器无效&#xff1f; 总结 上下两张图片…

基于单片机的空调温度控制器设计

摘 要 随着国民经济的发展和人民生活水平的提高&#xff0c;空调已被广泛应用于社会的各种场合。空调因具有节能、低噪、恒温控制、全天候运转、启动低频补偿、快速达到设定温度等性能&#xff0c;大大提高了其舒适性&#xff0c;得到越来越多的人们的喜爱。单片机和数字温度传…

ElasticSearch常见的索引_集群的备份与恢复方案

方案一&#xff1a;使用Elasticsearch的快照和恢复功能进行备份和恢复。该方案适用于集群整体备份与迁移&#xff0c;包括全量、增量备份和恢复。 方案二&#xff1a;通过reindex操作在集群内或跨集群同步数据。该方案适用于相同集群但不同索引层面的迁移&#xff0c;或者跨集…

【计算机网络】实验12:网际控制报文协议ICMP的应用

实验12 网际控制报文协议ICMP的应用 一、实验目的 验证ping命令和tracert命令的工作原理。 二、实验环境 Cisco Packet Tracer模拟器 三、实验过程 1.构建网络拓扑并进行信息标注&#xff0c;将所需要配置的IP地址写在对应的主机或者路由器旁边&#xff0c;如图1所示。 图…

Redis安装和Python练习(Windows11 + Python3.X + Pycharm社区版)

环境 Windows11 Python3.X Pycharm社区版 思路 1 github下载redis压缩包 &#xff0c;安装并启动redis服务&#xff0c;在客户端连接redis服务。 2 在pycharm中运行python程序&#xff0c;连接redis服务&#xff0c;熟悉redis的使用和巩固python语言。 3 python开发环境…

8.解决跨域问题的三种方案

开启域名&#xff0c;单点登录后&#xff0c;就使用最上面的接口了

【机器学习】基础知识:拟合度(Goodness of Fit)

拟合度概念及意义 拟合度&#xff08;Goodness of Fit&#xff09;是衡量统计模型对数据解释能力的指标&#xff0c;用于评价模型对观测数据的拟合效果。在回归分析、分类模型或其他预测模型中&#xff0c;拟合度是模型性能的重要衡量标准。 1. 拟合度的作用 拟合度的主要作用…

【Elasticsearch】实现用户行为分析

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;…

初识Linux · 线程同步

目录 前言&#xff1a; 认识条件变量 认识接口 快速使用接口 生产消费模型 前言&#xff1a; 前文我们介绍了线程互斥&#xff0c;线程互斥是为了防止多个线程对临界资源访问的时候出现了对一个变量同时操作的情况&#xff0c;对于线程互斥来说&#xff0c;我们使用到了锁…

使用 LlamaFactory 结合开源大语言模型实现文本分类:从数据集构建到 LoRA 微调与推理评估

文章目录 背景介绍文本分类数据集Lora 微调模型部署与推理期待模型的输出结果 文本分类评估代码 背景介绍 本文将一步一步地&#xff0c;介绍如何使用llamafactory框架利用开源大语言模型完成文本分类的实验&#xff0c;以 LoRA微调 qwen/Qwen2.5-7B-Instruct 为例。 文本分类…

【已解决】MacOS上VMware Fusion虚拟机打不开的解决方法

在使用VMware Fusion时&#xff0c;不少用户可能会遇到虚拟机无法打开的问题。本文将为大家提供一个简单有效的解决方法&#xff0c;只需删除一个文件&#xff0c;即可轻松解决这一问题。 一、问题现象 在MacOS系统上&#xff0c;使用VMware Fusion运行虚拟机时&#xff0c;有…

【教程】创建NVIDIA Docker共享使用主机的GPU

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;欢迎[点赞、收藏、关注]哦~ 这套是我跑完整理的。直接上干货&#xff0c;复制粘贴即可&#xff01; # 先安装toolkit sudo apt-get update sudo apt-get install -y ca-certifica…

设备CTA进网许可认证有哪些值得注意的测试内容?

设备进网许可认证的测试项目与测试内容有哪些?在CTA进网认证过程中是否存在需要注意的地方?本篇是英利检测针对这两点给大家进行的资料整理&#xff0c;帮助大家更进一步了解项目难点所在。 一、电磁兼容测试(EMC测试) 电磁兼容测试旨在评估设备在电磁环境中的表现&#xff0…