文章目录

  • 诉求
  • 相关技术
  • 思路展开
  • 相关步骤
    • pom配置
    • 服务端相关配置
    • 文本信息、用户广播处理逻辑
    • 前端功能代码
    • 功能测试
  • 小结

诉求

实现页面实时在线文本协同编辑,且显示当前同时编辑文本的用户。

相关技术

Springboot(2.7.0)+Websocket+javascript

思路展开

  1. 页面展示当前登陆用户
  2. 页面有文本输入框(包含编辑、保存按钮)
  3. 页面展示编辑当前文本的用户
  4. 服务端广播处理文本信息的以及协同用户

相关步骤

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实现实时在线文本协同编辑,并展示协同用户相关推荐

  1. js实现简单的文本框编辑

    js实现简单的文本框编辑 javascrip 编辑 <div id="ull"><input type="text"><butto ...

  2. 优雅的使用Js或CSS处理文本的截断与展示

    之前遇见一个问题,就是处理文本截断,然后可以手动切换文本是全展示和手动展示,因为这个问题比较常见,而且其实现方式有多种,于是决定总结一下,与读者分享. 前言 首先,我们看这样一个场景: 展开更多 其h ...

  3. 一款美观实用的在线文档编辑系统,支持Markdown语法

    说明:最近博主对文档程序小有需求,找了很久发现都是单页,而且还不支持移动端,不是很理想,所以就专门花了半天时间,写了一个,该文档程序基于graphql.nuxtjs.mongodb.keystonej ...

  4. ajax 实时进度_三分钟搭建websocket实时在线聊天,项目经理也不敢这么写

    我们先看一下下面这张图: 可以看到这是一个简易的聊天室,两个窗口的消息是实时发送与接收的,这个主要就是用我们今天要讲的websocket实现的. websocket是什么? websocket是一种网 ...

  5. 基于websocket的网页实时消息推送与在线聊天(上篇)

    文章目录 @[toc] 基于websocket的网页实时消息推送与在线聊天(上篇) "使用dwebsocket在django中实现websocket" websocket原理图 d ...

  6. JS实时检测文本框内容长度

    通过js代码实时监测,文本框内容的变化以及长度,下图是一个实际使用场景. HTML部分: <input id="Text1" type="text" οn ...

  7. 基于socket.io的实时在线选座系统

    基于socket.io的实时在线选座系统(demo) 前言 前段时间公司做一个关于剧院的项目,遇到了这样一种情况. 在高并发多用户同时选座的情况下,假设A用户进入选座页面,正在选择座位,此时还没有提交 ...

  8. FCKeditor在线文本编辑器初级应用

    2019独角兽企业重金招聘Python工程师标准>>> 首先从FCKeditor的官网( http://www.fckeditor.net/)下载该编辑器,我下载的版本是FCKedi ...

  9. 在线文本按列截取工具

    在线文本按列截取工具 在线文本按列截取工具 本工具支持按列截取文本行列表,如截取所有文本行第1至6位,则将开始截取位置设置为1,结束截取长度设置为6,如需从后面截取,请使用复数的开始截取位置. 若文本 ...

最新文章

  1. 任天堂遭史上最严重黑客攻击:完整源代码、设计文档及技术演示泄露
  2. ftp 工具_ftp,ftp工具多大
  3. java join yield_java中join和yield有什么区别?
  4. master分支 合并到main_10 月 1 日后,GitHub 默认分支不再叫master!
  5. vue判断列表中包含某一项_判断字符串中是否包含某个字符串
  6. bzoj 1040: [ZJOI2008]骑士
  7. 一次搞定各种数据库 SQL 执行计划:MySQL、Oracle、SQL Server、PostgreSQL 以及 SQLite
  8. Linux服务器 mysql5.7安装流程
  9. android打印机字体大小,热敏打印机字体大小设置,怎么设置打印机字体
  10. KGB知识图谱的功能和特色介绍
  11. 基于Proteus基本元器件的认识
  12. 尝试用visio画个等边三角形
  13. JS中的Storage
  14. 【优化充电】基于matlab遗传算法求解电动汽车充电统一管理优化问题(含负荷功率曲线对比图及充电计划)【含Matlab源码 2300期】
  15. sql取每组最新数据
  16. Vue UI组件库(Element UI库)
  17. 大型三甲医院医学影像PACS系统源码(三维重建)
  18. spring成神之路第三十八篇:@Scheduled @EnableScheduling 定时器详解
  19. vue项目设置服务器地址,vue项目配置后端服务器地址
  20. idea安装maven依赖包及配置过程,打开及运行项目

热门文章

  1. 七、后台入口及添加影院实现《仿淘票票系统前后端完全制作(除支付外)》
  2. 关于MFC中的MS Shell Dlg字体
  3. 如何理解wordcount
  4. mysql的WAL技术是什么_我们常听到的WAL到底是什么
  5. 按键精灵免字库本地识别OCR
  6. 排产易!APS系统如何选型?(上)
  7. NoSQL(MongoDB) + GraphQL 快速入门环境和资料
  8. 如果我们失联了,怎么办?
  9. OC学习--类别(Category)和类 (Class)
  10. DDD 领域驱动设计 - 架构(分层/六边形/RESTful)