Vue+Springboot用Websocket实现协同编辑

1. 项目介绍

在本文中,我们将介绍如何使用Vue.js和Spring Boot实现一个支持多人实时协同编辑的Web应用。通过WebSocket技术,我们可以实现文档的实时同步,让多个用户同时编辑同一份文档。

2. 技术栈

  • 前端:Vue.js 3 + Vuex
  • 后端:Spring Boot 2.x
  • WebSocket:Spring WebSocket
  • 数据库:MySQL
  • 其他:operational transformation (OT)算法

3. 后端实现

3.1 添加WebSocket依赖

xml:pom.xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

3.2 WebSocket配置

java:WebSocketConfig.java 复制代码
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(documentWebSocketHandler(), "/ws/document")
               .setAllowedOrigins("*");
    }
    
    @Bean
    public DocumentWebSocketHandler documentWebSocketHandler() {
        return new DocumentWebSocketHandler();
    }
}

3.3 WebSocket处理器

java:DocumentWebSocketHandler.java 复制代码
@Component
public class DocumentWebSocketHandler extends TextWebSocketHandler {
    private static final Map<String, Set<WebSocketSession>> documentSessions = new ConcurrentHashMap<>();
    
    @Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) {
        // 处理收到的消息
        DocumentOperation operation = parseOperation(message.getPayload());
        broadcastChange(operation);
    }
    
    private void broadcastChange(DocumentOperation operation) {
        // 广播变更给所有相关会话
        Set<WebSocketSession> sessions = documentSessions.get(operation.getDocumentId());
        if (sessions != null) {
            sessions.forEach(session -> {
                try {
                    session.sendMessage(new TextMessage(JSON.toJSONString(operation)));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
        }
    }
}

4. 前端实现

4.1 WebSocket连接管理

javascript:src/store/modules/websocket.js 复制代码
export default {
  state: {
    socket: null,
    connected: false
  },
  
  mutations: {
    SET_SOCKET(state, socket) {
      state.socket = socket;
    },
    SET_CONNECTED(state, status) {
      state.connected = status;
    }
  },
  
  actions: {
    connectWebSocket({ commit }, documentId) {
      const socket = new WebSocket(`ws://localhost:8080/ws/document?documentId=${documentId}`);
      
      socket.onopen = () => {
        commit('SET_CONNECTED', true);
      };
      
      socket.onmessage = (event) => {
        const operation = JSON.parse(event.data);
        // 处理收到的操作
        this.dispatch('handleDocumentOperation', operation);
      };
      
      commit('SET_SOCKET', socket);
    }
  }
}

4.2 编辑器组件

vue:src/components/Editor.vue 复制代码
<template>
  <div class="editor">
    <textarea
      v-model="content"
      @input="handleInput"
      @keyup="handleKeyup"
    ></textarea>
  </div>
</template>

<script>
export default {
  name: 'Editor',
  data() {
    return {
      content: '',
      version: 0
    }
  },
  methods: {
    handleInput(e) {
      const operation = {
        type: 'update',
        content: e.target.value,
        version: this.version++,
        documentId: this.$route.params.id
      };
      
      this.$store.state.websocket.socket.send(JSON.stringify(operation));
    }
  }
}
</script>

5. 实现冲突解决

为了处理多人同时编辑可能产生的冲突,我们需要实现操作转换(OT)算法:

javascript:src/utils/ot.js 复制代码
export function transformOperation(operation1, operation2) {
  // 实现操作转换逻辑
  if (operation1.version < operation2.version) {
    return transformContent(operation1, operation2);
  }
  return operation1;
}

function transformContent(baseOp, concurrentOp) {
  // 根据两个操作的内容和位置进行转换
  // 返回转换后的操作
}

6. 主要功能展示

  1. 实时同步
  • 用户A编辑文档时,变更实时推送给其他用户
  • 其他用户可以看到文档的实时更新
  1. 冲突处理
  • 多用户同时编辑时自动处理冲突
  • 保证所有用户看到的文档内容一致
  1. 断线重连
  • 检测到连接断开时自动重连
  • 重连后同步最新文档内容

7. 性能优化

  1. 消息节流
javascript 复制代码
import { throttle } from 'lodash';

const sendOperation = throttle((operation) => {
  socket.send(JSON.stringify(operation));
}, 100);
  1. 批量处理
java 复制代码
@Scheduled(fixedRate = 100)
public void processPendingOperations() {
    List<DocumentOperation> operations = pendingOperations.drain();
    if (!operations.isEmpty()) {
        broadcastChanges(operations);
    }
}

8. 总结

通过Vue.js和Spring Boot的结合,我们实现了一个基础的协同编辑功能。关键点包括:

  • WebSocket实现实时通信
  • OT算法处理并发冲突
  • 状态同步和断线重连
  • 性能优化

要构建一个生产级别的协同编辑系统,还需要考虑:

  • 权限控制
  • 历史记录
  • 离线支持
  • 更复杂的冲突解决策略
相关推荐
Java内核笔记8 分钟前
同一份知识库,4 种切分 × 3 种召回,纯关键词比纯向量高 13 个点
java·人工智能·spring boot
u01110267524 分钟前
Canvas 导出 PNG 时 quality 参数为什么不起作用
前端·javascript·vue.js
学长毕设2 小时前
基于springboot的社会志愿者管理系统-附源码
java·spring boot·后端
计算机编程-吉哥2 小时前
计算机毕业设计 基于 SpringBoot + Vue 的剧本杀系统 Java毕业设计【任务书、开题报告、中期报告、论文、源码】
java·vue.js·spring boot·毕业设计·课程设计·计算机毕业设计选题
这里是杨杨吖2 小时前
SpringCloud+Vue民宿房屋租赁系统 附带详细运行指导视频
vue.js·spring boot·spring cloud·房屋·民宿租赁
RuoyiOffice3 小时前
SpringBoot OA推荐:面向信创选型,看看这套企业协同平台
spring boot·vue3·信创·flowable·企业协同·ruoyi office·oa选型
jianxuan3 小时前
Spring Boot + Maven 接入 Allatori:从普通打包到可选混淆发布
spring boot·python·maven
周厉4 小时前
WebSocket 使用场景与实现方法:Java + Vue3 全栈实战
java·websocket·vue3·websocket双向通讯
RuoyiOffice5 小时前
llama.cpp + SpringBoot3:本地部署 Qwen3.8,接入 AgentOS 企业办公智能体
spring boot·springboot3·llama.cpp·spring ai·qwen3.8·agentos
学长毕设14 小时前
基于SpringBoot的青少年编程学习平台系统-附源码
spring boot·学习·青少年编程