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算法处理并发冲突
  • 状态同步和断线重连
  • 性能优化

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

  • 权限控制
  • 历史记录
  • 离线支持
  • 更复杂的冲突解决策略
相关推荐
粉末的沉淀2 分钟前
vue:Vite项目中高效管理纯色SVG图标的方案
前端·javascript·vue.js
卤蛋fg63 分钟前
vxe-table 列宽与行高拖拽调整:让表格布局极其灵活,拖拽功能非常强大
vue.js
向日的葵00635 分钟前
Vue 路由传参的三种方式(三)
vue.js·路由
如果超人不会飞1 小时前
TinyVue Checkbox复选框组件使用指南
前端·vue.js
如果超人不会飞1 小时前
TinyVue Radio单选框组件使用指南
vue.js
鲁班小子1 小时前
Vite resolve.dedupe 使用教程
vue.js·vite
如果超人不会飞1 小时前
TinyVue Input输入框组件使用指南
vue.js
如果超人不会飞1 小时前
TinyVue Pager分页组件使用指南
前端·vue.js
大刚测试开发实战2 小时前
TestHub重磅更新!AI用例生成增加流式输出、Markdown文档上传、模型配置检测、AI评审开关控制...
vue.js·后端·github
程序员阿卢2 小时前
01-基于springboot框架调用ollama下的模型完成基本功能
spring boot·后端·ollama·通义千问模型qwen