Springboot2.x+Websocket+js实现实时在线文本协同编辑,并展示协同用户
文章目录
- 诉求
- 相关技术
- 思路展开
- 相关步骤
- pom配置
- 服务端相关配置
- 文本信息、用户广播处理逻辑
- 前端功能代码
- 功能测试
- 小结
诉求
实现页面实时在线文本协同编辑,且显示当前同时编辑文本的用户。
相关技术
Springboot(2.7.0)+Websocket+javascript
思路展开
- 页面展示当前登陆用户
- 页面有文本输入框(包含编辑、保存按钮)
- 页面展示编辑当前文本的用户
- 服务端广播处理文本信息的以及协同用户
相关步骤
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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.0</version></parent><groupId>com.example</groupId><artifactId>demo</artifactId><version>0.0.1-SNAPSHOT</version><packaging>war</packaging><name>demo</name><description>Demo project for Spring Boot</description><properties><java.version>8</java.version><java.encoding>UTF-8</java.encoding><slf4j.version>1.7.30</slf4j.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- springboot集成websocket --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId><scope>provided</scope></dependency><!-- 引入日志管理相关依赖--><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>${slf4j.version}</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>${slf4j.version}</version></dependency><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-to-slf4j</artifactId><version>2.14.0</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.69</version></dependency></dependencies><build><pluginManagement><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.1</version><configuration><target>${java.version}</target><source>${java.version}</source><encoding>${java.encoding}</encoding></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><version>2.6</version></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-release-plugin</artifactId><configuration><arguments>-Prelease</arguments></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-source-plugin</artifactId><version>2.1</version><configuration><attach>true</attach></configuration><executions><execution><phase>compile</phase><goals><goal>jar</goal></goals></execution></executions></plugin></plugins></pluginManagement></build></project>
服务端相关配置
编写WebSocketConfig和WebSocketHandler配置类,实现对WebSocket的配置。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.*;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;/*** @author * @date 2023年01月31日 14:21*/
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {// @Override
// public void configureMessageBroker(MessageBrokerRegistry registry) {// registry.enableSimpleBroker("/topic");
// registry.setApplicationDestinationPrefixes("/app");
// }@Overridepublic void registerStompEndpoints(StompEndpointRegistry registry) {registry.addEndpoint("/doc-collaboration").withSockJS();}@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;import java.io.IOException;
import java.util.ArrayList;
import java.util.List;/*** handler * @date2023年01月31日 14:22*/
@Component
public class WebSocketHandler extends TextWebSocketHandler {private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketHandler.class);private static final List<WebSocketSession> sessions = new ArrayList<>();@Overridepublic void handleTextMessage(WebSocketSession session, TextMessage message) {LOGGER.info("Received message: {}", message.getPayload());for (WebSocketSession webSocketSession : sessions) {try {webSocketSession.sendMessage(message);} catch (IOException e) {LOGGER.error("Error: {}", e.getMessage());}}}@Overridepublic void afterConnectionEstablished(WebSocketSession session) {sessions.add(session);}@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus status) {sessions.remove(session);}
}
文本信息、用户广播处理逻辑
定义 WebSocket 端点以处理来自客户端的传入消息。
/*** @author * @date 2023年01月31日 11:19*/import com.alibaba.fastjson.JSON;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;@ServerEndpoint("/doc-collaboration")
@Component
@Slf4j
public class DocWebSocketServer {private static Set<Session> sessions = new HashSet<>();private static Set<String> editingUsers = new HashSet<>();private static String content = "";@OnOpenpublic void onOpen(Session session) {sessions.add(session);}@OnClosepublic void onClose(Session session) {sessions.remove(session);String username = (String) session.getUserProperties().get("username");if (username != null) {editingUsers.remove(username);broadcastEditingUsers();}}@OnMessagepublic void onMessage(String message, Session session) {Gson gson = new Gson();Map<String, Object> data = gson.fromJson(message, Map.class);String type = (String) data.get("type");log.info("Message type: {}, message data: {}", type, data);String jsonStr = "";switch (type) {case "connect":String username = (String) data.get("username");session.getUserProperties().put("username", username);jsonStr = JSON.toJSONString(new HashMap<String, Object>() {{put("type", "update");put("content", content);}});broadcast(jsonStr);break;case "update":content = (String) data.get("content");jsonStr = JSON.toJSONString(new HashMap<String, Object>() {{put("type", "update");put("content", content);}});broadcast(jsonStr);break;case "start-editing":username = (String) session.getUserProperties().get("username");editingUsers.add(username);broadcastEditingUsers();break;case "stop-editing":username = (String) session.getUserProperties().get("username");editingUsers.remove(username);broadcastEditingUsers();break;case "getUser":broadcastEditingUsers();break;}}/*** 广播当前文本信息* @param message*/private void broadcast(String message) {log.info("message {}", message);for (Session session : sessions) {try {session.getBasicRemote().sendText(message);} catch (IOException e) {e.printStackTrace();}}}/*** 广播当前正在编辑文本的用户*/private void broadcastEditingUsers() {broadcast(JSON.toJSONString(new HashMap<String, Object>() {{put("type", "editing");put("editingUsers", new ArrayList<>(editingUsers));}}));}
}
前端功能代码
创建一个 JavaScript 客户端,它与端点建立 WebSocket 连接并将更新发送到服务器。展示当前用户以及同时编辑文本的人员名称。
好久没写前端了,写起来有点费劲!
Springboot2.x+Websocket+js实现实时在线文本协同编辑,并展示协同用户相关推荐
- js实现简单的文本框编辑
js实现简单的文本框编辑 javascrip 编辑 <div id="ull"><input type="text"><butto ...
- 优雅的使用Js或CSS处理文本的截断与展示
之前遇见一个问题,就是处理文本截断,然后可以手动切换文本是全展示和手动展示,因为这个问题比较常见,而且其实现方式有多种,于是决定总结一下,与读者分享. 前言 首先,我们看这样一个场景: 展开更多 其h ...
- 一款美观实用的在线文档编辑系统,支持Markdown语法
说明:最近博主对文档程序小有需求,找了很久发现都是单页,而且还不支持移动端,不是很理想,所以就专门花了半天时间,写了一个,该文档程序基于graphql.nuxtjs.mongodb.keystonej ...
- ajax 实时进度_三分钟搭建websocket实时在线聊天,项目经理也不敢这么写
我们先看一下下面这张图: 可以看到这是一个简易的聊天室,两个窗口的消息是实时发送与接收的,这个主要就是用我们今天要讲的websocket实现的. websocket是什么? websocket是一种网 ...
- 基于websocket的网页实时消息推送与在线聊天(上篇)
文章目录 @[toc] 基于websocket的网页实时消息推送与在线聊天(上篇) "使用dwebsocket在django中实现websocket" websocket原理图 d ...
- JS实时检测文本框内容长度
通过js代码实时监测,文本框内容的变化以及长度,下图是一个实际使用场景. HTML部分: <input id="Text1" type="text" οn ...
- 基于socket.io的实时在线选座系统
基于socket.io的实时在线选座系统(demo) 前言 前段时间公司做一个关于剧院的项目,遇到了这样一种情况. 在高并发多用户同时选座的情况下,假设A用户进入选座页面,正在选择座位,此时还没有提交 ...
- FCKeditor在线文本编辑器初级应用
2019独角兽企业重金招聘Python工程师标准>>> 首先从FCKeditor的官网( http://www.fckeditor.net/)下载该编辑器,我下载的版本是FCKedi ...
- 在线文本按列截取工具
在线文本按列截取工具 在线文本按列截取工具 本工具支持按列截取文本行列表,如截取所有文本行第1至6位,则将开始截取位置设置为1,结束截取长度设置为6,如需从后面截取,请使用复数的开始截取位置. 若文本 ...
最新文章
- 任天堂遭史上最严重黑客攻击:完整源代码、设计文档及技术演示泄露
- ftp 工具_ftp,ftp工具多大
- java join yield_java中join和yield有什么区别?
- master分支 合并到main_10 月 1 日后,GitHub 默认分支不再叫master!
- vue判断列表中包含某一项_判断字符串中是否包含某个字符串
- bzoj 1040: [ZJOI2008]骑士
- 一次搞定各种数据库 SQL 执行计划:MySQL、Oracle、SQL Server、PostgreSQL 以及 SQLite
- Linux服务器 mysql5.7安装流程
- android打印机字体大小,热敏打印机字体大小设置,怎么设置打印机字体
- KGB知识图谱的功能和特色介绍
- 基于Proteus基本元器件的认识
- 尝试用visio画个等边三角形
- JS中的Storage
- 【优化充电】基于matlab遗传算法求解电动汽车充电统一管理优化问题(含负荷功率曲线对比图及充电计划)【含Matlab源码 2300期】
- sql取每组最新数据
- Vue UI组件库(Element UI库)
- 大型三甲医院医学影像PACS系统源码(三维重建)
- spring成神之路第三十八篇:@Scheduled @EnableScheduling 定时器详解
- vue项目设置服务器地址,vue项目配置后端服务器地址
- idea安装maven依赖包及配置过程,打开及运行项目