将部门同步功能重构为**数据查询**和**数据同步**两个独立的服务,实现职责分离和灵活性提升。
┌─────────────────────────────────────────┐
│ DepartmentSyncServiceImpl │
│ │
│ ┌─────────────────────────────────┐ │
│ │ syncBranchDepartments() │ │
│ │ ├─ 查询 SQL Server │ │
│ │ └─ 写入 MySQL │ │
│ └─────────────────────────────────┘ │
└─────────────────────────────────────────┘
问题:
- ❌ 数据查询和同步逻辑耦合
- ❌ 无法使用外部数据源
- ❌ 难以扩展其他数据来源
┌──────────────────────────────────────────────────────────┐
│ DepartmentSyncDataServiceImpl (新增) │
│ 职责:从 SQL Server 查询数据 │
│ │
│ ├─ getBranchDepartments() │
│ └─ 返回 List<DepartmentSyncDTO> │
└──────────────────────────────────────────────────────────┘
│
v
┌──────────────────────────────────────────────────────────┐
│ DepartmentSyncServiceImpl (重构) │
│ 职责:接收数据并写入 MySQL │
│ │
│ ├─ syncBranchDepartments() │
│ │ └─ 调用 DepartmentSyncDataService 获取数据 │
│ │ │
│ └─ syncBranchDepartments(List<DepartmentSyncDTO>) │
│ └─ 接收外部传入的数据进行同步 │
└──────────────────────────────────────────────────────────┘
优势:
- ✅ 职责单一,易于维护
- ✅ 支持外部数据源
- ✅ 灵活性高,易于扩展
文件路径: ruoyi-system/src/main/java/com/ruoyi/system/service/IDepartmentSyncDataService.java
职责: 定义从 SQL Server 查询数据的接口
public interface IDepartmentSyncDataService {
/**
* 从 SQL Server 查询合作单位下的所有分公司数据
*
* @return 分公司列表
*/
List<DepartmentSyncDTO> getBranchDepartments();
}
文件路径: ruoyi-system/src/main/java/com/ruoyi/system/service/impl/DepartmentSyncDataServiceImpl.java
职责: 专门负责从 SQL Server 查询部门数据
关键特性:
```java
@Service
public class DepartmentSyncDataServiceImpl implements IDepartmentSyncDataService {
@Autowired
private DepartmentSyncMapper departmentSyncMapper; // 带 @DataSource 注解
@Override
public List<DepartmentSyncDTO> getBranchDepartments() {
log.info("开始从 SQL Server 查询分公司数据...");
// 自动切换到 SQL Server 数据源
List<DepartmentSyncDTO> branchDepts = departmentSyncMapper.selectBranchDepartments();
log.info("从 SQL Server 查询到 {} 条分公司数据", branchDepts.size());
return branchDepts;
}
}
```
数据流: DepartmentSyncDataServiceImpl ↓ DepartmentSyncMapper (@DataSource(SQLSERVER)) ↓ SQL Server 数据库 (uv_department) ↓ 返回 List<DepartmentSyncDTO>
文件路径: ruoyi-system/src/main/java/com/ruoyi/system/service/IDepartmentSyncService.java
变化: 新增重载方法,支持外部数据源
public interface IDepartmentSyncService {
/**
* 同步分公司和部门数据(从 SQL Server 查询并同步到 MySQL)
*/
AjaxResult syncBranchDepartments();
/**
* 同步分公司和部门数据(使用外部传入的数据源)
*
* @param branchDepts 外部传入的分公司数据列表
*/
AjaxResult syncBranchDepartments(List<DepartmentSyncDTO> branchDepts);
}
文件路径: ruoyi-system/src/main/java/com/ruoyi/system/service/impl/DepartmentSyncServiceImpl.java
变化:
1. 移除对 DepartmentSyncMapper 的直接依赖
2. 注入 IDepartmentSyncDataService 获取数据
3. 新增 syncBranchDepartments(List<DepartmentSyncDTO>) 方法
重构后的代码:
@Service
public class DepartmentSyncServiceImpl implements IDepartmentSyncService {
@Autowired
private IDepartmentSyncDataService departmentSyncDataService; // 数据查询服务
@Autowired
private SysDeptMapper sysDeptMapper; // MySQL 操作
// 方法 1: 内部查询 + 同步
@Override
@Transactional
public AjaxResult syncBranchDepartments() {
// 调用数据查询服务获取 SQL Server 数据
List<DepartmentSyncDTO> branchDepts = departmentSyncDataService.getBranchDepartments();
if (branchDepts == null || branchDepts.isEmpty()) {
return AjaxResult.warn("未获取到需要同步的分公司数据");
}
// 调用重载方法执行同步
return syncBranchDepartments(branchDepts);
}
// 方法 2: 外部数据源 + 同步(新增)
@Override
@Transactional
public AjaxResult syncBranchDepartments(List<DepartmentSyncDTO> branchDepts) {
if (branchDepts == null || branchDepts.isEmpty()) {
return AjaxResult.warn("传入的部门数据为空");
}
log.info("开始同步 {} 条分公司数据到 MySQL 数据库...", branchDepts.size());
// 同步逻辑(只涉及 MySQL 操作)
// ...
}
}
数据流:
syncBranchDepartments()
↓
调用 departmentSyncDataService.getBranchDepartments()
↓
获取 List<DepartmentSyncDTO>
↓
调用 syncBranchDepartments(List)
↓
写入 MySQL 数据库
外部调用者提供 List<DepartmentSyncDTO>
↓
syncBranchDepartments(List)
↓
写入 MySQL 数据库
文件路径: ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/DepartmentSyncController.java
变化: 新增接口支持外部数据源
@RestController
@RequestMapping("/system/dept/sync")
public class DepartmentSyncController {
@Autowired
private IDepartmentSyncService departmentSyncService;
/**
* 接口 1: 同步分公司和部门数据(从 SQL Server 查询并同步)
*/
@PostMapping("/branch")
public AjaxResult syncBranchDepartments() {
return departmentSyncService.syncBranchDepartments();
}
/**
* 接口 2: 同步分公司和部门数据(使用外部传入的数据源)
*/
@PostMapping("/branch/data")
public AjaxResult syncBranchDepartmentsWithData(@RequestBody List<DepartmentSyncDTO> branchDepts) {
return departmentSyncService.syncBranchDepartments(branchDepts);
}
}
POST http://localhost:8080/system/dept/sync/branch
执行流程:
1. Controller 调用 departmentSyncService.syncBranchDepartments()
2. Service 调用 departmentSyncDataService.getBranchDepartments()
3. 自动切换到 SQL Server 查询数据
4. 将数据写入 MySQL
POST http://localhost:8080/system/dept/sync/branch/data
Content-Type: application/json
[
{
"departmentId": 1001,
"departmentName": "湛江--护士",
"parentId": 100,
"parentName": "合作单位"
},
{
"departmentId": 1002,
"departmentName": "湛江--车队",
"parentId": 100,
"parentName": "合作单位"
}
]
执行流程:
1. Controller 接收 JSON 数据并转换为 List<DepartmentSyncDTO>
2. Controller 调用 departmentSyncService.syncBranchDepartments(branchDepts)
3. Service 直接将数据写入 MySQL
@Service
public class CustomSyncService {
@Autowired
private IDepartmentSyncService departmentSyncService;
public void syncFromExternalSystem() {
// 1. 从其他系统获取数据(如 HTTP API、消息队列等)
List<DepartmentSyncDTO> externalData = fetchDataFromExternalSystem();
// 2. 进行数据预处理
List<DepartmentSyncDTO> processedData = preprocessData(externalData);
// 3. 调用同步服务
AjaxResult result = departmentSyncService.syncBranchDepartments(processedData);
log.info("同步结果: {}", result.get("msg"));
}
}
@Service
public class BatchSyncService {
@Autowired
private IDepartmentSyncDataService departmentSyncDataService;
@Autowired
private IDepartmentSyncService departmentSyncService;
public void batchSync() {
// 1. 从 SQL Server 获取数据
List<DepartmentSyncDTO> sqlServerData = departmentSyncDataService.getBranchDepartments();
// 2. 从其他来源获取数据
List<DepartmentSyncDTO> otherData = getDataFromOtherSource();
// 3. 合并数据
List<DepartmentSyncDTO> allData = new ArrayList<>();
allData.addAll(sqlServerData);
allData.addAll(otherData);
// 4. 统一同步
departmentSyncService.syncBranchDepartments(allData);
}
}
| 接口 | 路径 | 数据来源 | 适用场景 |
|---|---|---|---|
| 接口 1 | POST /system/dept/sync/branch |
内部查询 SQL Server | 常规定时同步 |
| 接口 2 | POST /system/dept/sync/branch/data |
外部传入 JSON | 手动数据导入、数据预处理、多源整合 |
定时任务可以继续使用原有方式,无需修改:
@Component("oaSyncTask")
public class OaSyncTask {
@Autowired
private IDepartmentSyncService departmentSyncService;
public void syncOaData() {
// 自动从 SQL Server 查询并同步
AjaxResult result = departmentSyncService.syncBranchDepartments();
log.info("定时同步结果: {}", result.get("msg"));
}
}
// 扩展:支持其他数据源
public interface IDepartmentSyncDataService {
List<DepartmentSyncDTO> getBranchDepartments(); // SQL Server
List<DepartmentSyncDTO> getBranchDepartmentsFromOracle(); // Oracle
List<DepartmentSyncDTO> getBranchDepartmentsFromAPI(); // HTTP API
}
@Test
public void testSyncWithMockData() {
// 创建测试数据
List<DepartmentSyncDTO> testData = createTestData();
// 测试同步逻辑
AjaxResult result = departmentSyncService.syncBranchDepartments(testData);
// 验证结果
assertEquals(200, result.get("code"));
}
无需修改!原有调用方式完全兼容:
// 原有代码
departmentSyncService.syncBranchDepartments();
// 仍然有效,行为不变
使用新增的重载方法:
// 新功能:使用外部数据源
List<DepartmentSyncDTO> externalData = getExternalData();
departmentSyncService.syncBranchDepartments(externalData);
| 文件 | 说明 |
|---|---|
IDepartmentSyncDataService.java |
数据查询服务接口 |
DepartmentSyncDataServiceImpl.java |
数据查询服务实现 |
| 文件 | 变化 |
|---|---|
IDepartmentSyncService.java |
新增重载方法 |
DepartmentSyncServiceImpl.java |
重构实现,支持外部数据源 |
DepartmentSyncController.java |
新增接口 /branch/data |
| 文件 | 说明 |
|---|---|
DepartmentSyncMapper.java |
Mapper 接口不变 |
DepartmentSyncMapper.xml |
SQL 映射不变 |
OaSyncTask.java |
定时任务不变 |
通过本次重构,实现了:
✅ 职责分离: 数据查询和同步逻辑解耦
✅ 灵活性提升: 支持多种数据来源
✅ 易于扩展: 可轻松添加新的数据源
✅ 向后兼容: 原有代码无需修改
✅ 易于测试: 可使用 Mock 数据进行单元测试