# 旧系统同步功能实现总结 ## 📋 功能概述 实现了新系统的急救转运任务自动同步到旧ASP系统(`admin_save_19.gds`)的完整功能,包括: - ✅ 任务创建后自动异步同步到旧系统 - ✅ 定时任务批量同步未同步成功的任务 - ✅ 完整的同步状态跟踪和错误记录 - ✅ 手动重试失败任务的能力 --- ## 🗂️ 文件清单 ### 1. 数据库相关 (1个文件) #### `sql/add_legacy_system_id.sql` - 在 `sys_task_emergency` 表添加旧系统ID字段 - 添加同步状态、同步时间、错误信息字段 - 在 `sys_task` 表添加同步标记字段 ### 2. 配置类 (1个文件) #### `ruoyi-common/src/main/java/com/ruoyi/common/config/LegacySystemConfig.java` - 旧系统配置类 - 支持从 `application.yml` 读取配置 - 包含: baseUrl, enabled, timeout等配置项 ### 3. 服务层 (2个文件) #### `ruoyi-system/src/main/java/com/ruoyi/system/service/ILegacySystemSyncService.java` - 旧系统同步服务接口 - 定义三个核心方法: - `syncEmergencyTaskToLegacy()` - 同步单个任务 - `batchSyncPendingTasks()` - 批量同步 - `retrySyncTask()` - 重试失败任务 #### `ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacySystemSyncServiceImpl.java` - 旧系统同步服务实现类 (392行) - 核心功能: - HTTP POST请求封装 - 参数映射和转换 - 响应解析 (OK:ServiceOrdID格式) - 同步状态管理 - 异常处理和重试机制 ### 4. 定时任务 (1个文件) #### `ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/LegacySystemSyncTask.java` - 定时任务类 - 提供两个方法: - `syncPendingTasks()` - 批量同步待处理任务 - `syncTask(taskId)` - 同步指定任务 ### 5. 实体类修改 (2个文件) #### `ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskEmergency.java` 添加字段: - `legacyServiceOrdId` - 旧系统ServiceOrdID - `syncStatus` - 同步状态 - `syncTime` - 同步时间 - `syncErrorMsg` - 同步错误信息 #### `ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTask.java` 添加字段: - `legacySynced` - 旧系统同步标记 ### 6. Mapper修改 (3个文件) #### `ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskEmergencyMapper.java` 添加方法: - `selectPendingSyncTasks()` - 查询待同步任务列表 #### `ruoyi-system/src/main/resources/mapper/system/SysTaskEmergencyMapper.xml` - 添加新字段映射 - 实现 `selectPendingSyncTasks` 查询 #### `ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml` - 添加 `legacy_synced` 字段映射 ### 7. 业务逻辑修改 (1个文件) #### `ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java` - 注入 `ILegacySystemSyncService` - 在任务创建后异步调用同步服务 ### 8. 配置文件 (1个文件) #### `ruoyi-admin/src/main/resources/application-legacy.yml` - 配置示例文件 - 包含所有可配置项和说明 ### 9. 文档 (3个文件) #### `prd/旧系统同步配置说明.md` - 详细的配置和使用文档 (332行) - 包含: 功能说明、配置步骤、监控查询、故障排查 #### `prd/旧系统同步-快速开始.md` - 快速配置指南 (212行) - 5分钟快速上手 #### `prd/旧系统同步功能实现总结.md` - 本文档,总结所有实现内容 #### `prd/旧系统同步参数映射表.md` - 完整的参数映射说明 (277行) - 包含66个参数的详细映射关系 - adminID参数使用说明 --- ## 🏗️ 架构设计 ### 同步流程图 ``` ┌─────────────────┐ │ 创建急救任务 │ └────────┬────────┘ │ ▼ ┌─────────────────┐ │ 保存到数据库 │ │ (sync_status=0) │ └────────┬────────┘ │ ├────────────────────────┐ │ │ ▼ ▼ ┌─────────────────┐ ┌──────────────┐ │ 自动异步同步 │ │ 定时任务 │ │ (2秒延迟) │ │ (每10分钟) │ └────────┬────────┘ └──────┬───────┘ │ │ └──────────┬───────────┘ ▼ ┌─────────────────────┐ │ 调用旧系统API │ │ POST admin_save_19 │ └──────────┬──────────┘ │ ┌──────────┴──────────┐ ▼ ▼ ┌─────────┐ ┌─────────┐ │ 成功 │ │ 失败 │ │ (状态2) │ │ (状态3) │ └────┬────┘ └────┬────┘ │ │ ▼ ▼ ┌─────────┐ ┌─────────┐ │保存ID │ │记录错误 │ └─────────┘ │等待重试 │ └─────────┘ ``` ### 数据流转 ``` SysTask (任务主表) ↓ (task_id) SysTaskEmergency (急救扩展表) ├─ legacy_service_ord_id (旧系统ID) ├─ sync_status (0/1/2/3) ├─ sync_time └─ sync_error_msg ↓ LegacySystemSyncService ↓ (HTTP POST) 旧系统 admin_save_19.gds ↓ (返回: OK:ServiceOrdID) 更新 legacy_service_ord_id ``` --- ## 🔑 核心技术点 ### 1. HTTP通信 ```java // 使用 HttpURLConnection 发送POST请求 // 支持自定义超时、编码、表单提交 conn.setRequestMethod("POST"); conn.setConnectTimeout(30000); conn.setReadTimeout(30000); conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"); ``` ### 2. 异步处理 ```java // 创建任务后异步同步,避免阻塞主流程 new Thread(() -> { Thread.sleep(2000); // 等待事务提交 legacySystemSyncService.syncEmergencyTaskToLegacy(taskId); }).start(); ``` ### 3. 状态机管理 ``` 0 (未同步) → 1 (同步中) → 2 (成功) / 3 (失败) ↓ 等待定时任务重试 ``` ### 4. 数据映射 - **adminID**: 使用任务创建人ID (`task.getCreatorId()`) - 新系统字段 → 旧系统字段自动映射 (共66个参数) - 性别转换: 0→男, 1→女 - 固定值注入: ServiceOrdClass=JJ, ServiceOrdSource=10 - 详细参数映射请查看: [旧系统同步参数映射表.md](./旧系统同步参数映射表.md) ### 5. 容错机制 - 同步失败不影响主业务 - 记录详细错误信息 - 支持自动重试 - 防止重复同步 --- ## 📊 数据库变更 ### sys_task_emergency 表 | 字段名 | 类型 | 说明 | |--------|------|------| | legacy_service_ord_id | BIGINT | 旧系统ServiceOrdID | | sync_status | TINYINT | 0-未同步, 1-同步中, 2-成功, 3-失败 | | sync_time | DATETIME | 同步时间 | | sync_error_msg | VARCHAR(500) | 错误信息 | ### sys_task 表 | 字段名 | 类型 | 说明 | |--------|------|------| | legacy_synced | TINYINT | 0-未同步, 1-已同步 | ### 索引 ```sql -- 加速同步状态查询 ALTER TABLE sys_task_emergency ADD INDEX idx_sync_status (sync_status); -- 加速旧系统ID查询 ALTER TABLE sys_task_emergency ADD INDEX idx_legacy_service_ord_id (legacy_service_ord_id); -- 加速主表同步标记查询 ALTER TABLE sys_task ADD INDEX idx_legacy_synced (legacy_synced); ``` --- ## ⚙️ 配置项说明 | 配置项 | 必填 | 默认值 | 说明 | |--------|------|--------|------| | `legacy.system.base-url` | ✅ | 无 | 旧系统基础URL | | `legacy.system.emergency-create-path` | ❌ | /admin_save_19.gds | 接口路径 | | `legacy.system.connect-timeout` | ❌ | 30000 | 连接超时(毫秒) | | `legacy.system.read-timeout` | ❌ | 30000 | 读取超时(毫秒) | | `legacy.system.enabled` | ❌ | true | 是否启用 | | `legacy.system.charset` | ❌ | UTF-8 | 字符编码 | --- ## 🧪 测试建议 ### 单元测试 ```java @Test public void testSyncEmergencyTask() { Long taskId = 123L; Long serviceOrdId = legacySystemSyncService.syncEmergencyTaskToLegacy(taskId); assertNotNull(serviceOrdId); assertTrue(serviceOrdId > 0); } ``` ### 集成测试 1. 创建测试任务 2. 等待2-3秒 3. 查询同步状态 4. 验证旧系统是否收到数据 ### 压力测试 - 批量创建100个任务 - 观察同步成功率 - 监控系统资源占用 --- ## 📈 监控指标 ### 关键指标 1. **同步成功率**: 成功数 / 总数 * 100% 2. **平均同步耗时**: 从创建到同步成功的时间 3. **同步失败率**: 失败数 / 总数 * 100% 4. **待同步任务堆积数**: sync_status=0的任务数 ### SQL监控 ```sql -- 今日同步统计 SELECT COUNT(*) AS 总数, SUM(CASE WHEN sync_status = 2 THEN 1 ELSE 0 END) AS 成功数, SUM(CASE WHEN sync_status = 3 THEN 1 ELSE 0 END) AS 失败数, CONCAT(ROUND(SUM(CASE WHEN sync_status = 2 THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 2), '%') AS 成功率 FROM sys_task_emergency WHERE DATE(create_time) = CURDATE(); ``` --- ## 🔒 安全考虑 ### 已实现 - ✅ 防止SQL注入 (使用MyBatis参数化查询) - ✅ 防止重复同步 (检查legacy_service_ord_id) - ✅ 异常隔离 (同步失败不影响主业务) - ✅ 配置开关 (可随时禁用) ### 待加强 - ⚠️ HTTPS通信 (建议生产环境使用) - ⚠️ 数据加密 (患者敏感信息) - ⚠️ 访问令牌 (如旧系统支持) - ⚠️ IP白名单 (限制访问来源) --- ## 🚀 性能优化 ### 当前设计 - 异步同步: 不阻塞主流程 - 批量限制: 每次最多100个 - 请求间隔: 每个任务间隔1秒 - 超时控制: 30秒超时 ### 可优化点 1. **连接池**: 复用HTTP连接 2. **批量接口**: 如旧系统支持批量创建 3. **消息队列**: 使用RabbitMQ/Kafka异步处理 4. **缓存机制**: 缓存医院、科室等字典数据 --- ## 📝 部署清单 ### 开发环境 - [x] 执行数据库脚本 - [x] 配置 `application-dev.yml` - [x] 重启应用 - [x] 创建定时任务 - [x] 测试同步功能 ### 生产环境 - [ ] 备份数据库 - [ ] 执行数据库脚本 - [ ] 配置 `application-prod.yml` - [ ] 重启应用 (选择低峰期) - [ ] 创建定时任务 - [ ] 监控同步状态 - [ ] 准备回滚方案 --- ## 🎯 后续优化建议 1. **管理界面** - 在后台添加同步状态查看页面 - 提供手动重试按钮 - 展示同步统计图表 2. **告警通知** - 同步失败超过阈值时发送邮件/短信 - 接入企业微信/钉钉机器人 3. **双向同步** - 旧系统状态变更同步回新系统 - 实现数据一致性校验 4. **历史数据同步** - 提供批量同步历史任务的工具 - 支持指定日期范围同步 --- ## 👨‍💻 开发者备注 ### 关键类说明 1. **LegacySystemConfig**: 配置管理,Spring自动注入 2. **LegacySystemSyncServiceImpl**: 核心同步逻辑,HTTP通信 3. **LegacySystemSyncTask**: 定时任务入口,供Quartz调用 4. **SysTaskServiceImpl**: 任务创建后触发异步同步 ### 日志级别 - INFO: 同步成功、批量同步完成 - WARN: 配置未启用、任务已同步 - ERROR: 同步失败、网络异常 ### 异常处理 - 所有异常不向上抛出 - 记录到 sync_error_msg - 更新 sync_status = 3 - 等待定时任务重试 --- ## 📞 联系信息 - **项目位置**: `d:\project\急救转运\code\Api\RuoYi-Vue-master` - **文档位置**: `prd/` 目录 - **技术栈**: Spring Boot + MyBatis + Quartz + HttpURLConnection --- **完成时间**: 2025-01-20 **版本**: v1.0 **状态**: ✅ 已完成,待测试