zn-cloud/issues/流程附件上传机制优化.md
aikai 79e96d3546 feat(infra): 实现 MinIO 分片上传功能
- 新增分片上传相关接口和 VO 类
- 实现分片上传服务,包括初始化、获取预签名 URL、完成上传和取消上传
- 添加分片上传会话的数据库表结构和 Mapper
- 优化错误处理和参数验证
2025-07-03 11:18:53 +08:00

153 lines
5.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 流程附件上传机制优化
## 任务概述
`BpmProcessInstanceController.uploadAttachment` 方法从硬编码映射改为通过配置表动态获取实体类和Mapper类`ProcessQueryServiceImpl` 保持一致的反射机制。
## 实施方案
**方案1完全使用配置表机制已采用**
- 移除硬编码的 `entityTypeMap`
- 注入 `ProcessMappingConfigService`
- 修改 `resolveEntityType` 方法通过配置表动态获取类信息
- 参数兼容:`processType` 映射到 `processCode`
## 具体修改
### 1. 移除硬编码机制
```java
// 删除了以下内容:
private final Map<String, List> entityTypeMap = new ConcurrentHashMap<>();
@PostConstruct
public void init() {
// 注册支持的实体类型
entityTypeMap.put("oa_reimbursement", new ArrayList<Class<?>>(Arrays.asList(BpmOAReimbursementDO.class, BpmOAReimbursementMapper.class)));
// ... 其他30多个映射关系
}
```
### 2. 新增依赖注入
```java
@Resource
private ProcessMappingConfigService processMappingConfigService;
```
### 3. 重构解析方法
```java
private List<Class<?>> resolveEntityType(String processCode) {
try {
// 1. 获取流程映射配置
BpmProcessMappingConfigDO config = processMappingConfigService.getProcessMappingConfigByCode(processCode);
if (config == null) {
log.error("[resolveEntityType][流程映射配置不存在] processCode={}", processCode);
throw exception(PROCESS_MAPPING_CONFIG_NOT_EXISTS);
}
// 2. 动态加载实体类和Mapper类
Class<?> entityClass = ClassUtil.loadClass(config.getEntityClass());
Class<?> mapperClass = ClassUtil.loadClass(config.getMapperClass());
// 3. 验证Mapper类是否可获取Bean实例
SpringUtil.getBean(mapperClass);
return Arrays.asList(entityClass, mapperClass);
} catch (Exception e) {
log.error("[resolveEntityType][解析流程类型失败] processCode={}", processCode, e);
throw new ServiceException(500, String.format("不支持的流程类型: %s, 错误信息: %s", processCode, e.getMessage()));
}
}
```
### 4. 新增import语句
```java
import cn.hutool.core.util.ClassUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.iocoder.yudao.module.bpm.dal.dataobject.processmapping.BpmProcessMappingConfigDO;
import cn.iocoder.yudao.module.bpm.service.processmapping.ProcessMappingConfigService;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_MAPPING_CONFIG_NOT_EXISTS;
```
## 技术优势
### 1. 统一反射机制
- ✅ 与 `ProcessQueryServiceImpl` 采用相同的配置表查询方式
- ✅ 使用相同的工具类(`ClassUtil`, `SpringUtil`
- ✅ 统一的异常处理和错误码
### 2. 动态配置支持
- ✅ 支持通过配置表动态添加新的流程类型
- ✅ 无需修改代码和重启服务
- ✅ 配置变更可通过管理界面完成
### 3. 代码质量提升
- ✅ 消除了30多行硬编码映射
- ✅ 减少了代码维护成本
- ✅ 提高了系统的可扩展性
### 4. 兼容性保证
- ✅ API接口保持不变
- ✅ 前端代码无需修改
-`processType` 参数直接作为 `processCode` 使用
## 配置表结构
系统依赖 `bmp_process_mapping_config` 表的以下字段:
- `process_code`: 流程唯一标识(对应前端传入的 `processType`
- `entity_class`: 实体类全限定名
- `mapper_class`: Mapper接口全限定名
## 使用示例
前端调用方式保持不变:
```javascript
{
"processType": "oa_reimbursement", // 会作为processCode查询配置表
"processBusinessId": 123,
"fileItems": [...]
}
```
后台会自动:
1. 根据 `processType="oa_reimbursement"` 查询配置表
2. 获取对应的实体类和Mapper类
3. 动态实例化并调用附件更新服务
## 执行时间
2024年12月19日
## 状态
✅ 已完成(已优化架构)
## 后续优化
**2024年12月19日 - 架构优化:**
### 1. 分层重构
- **问题**`resolveEntityType` 方法不应放在Controller层
- **解决**:将类型解析逻辑移至 `BpmOAAttachmentService` 服务层
- **优势**符合分层架构原则Controller只负责接口调用
### 2. 使用ReflectionInvoker工具类
- **问题**`BpmOAAttachmentServiceImpl.updateAttachment` 使用手动反射
- **解决**:替换为 `ReflectionInvoker.invokeMapperMethod` 调用
- **优势**:更安全、统一的反射机制,支持代理类处理
### 3. 优化后的调用链
```
Controller -> Service (类型解析) -> Service (附件更新) -> ReflectionInvoker (Mapper调用)
```
### 4. 主要变更文件
- `BpmOAAttachmentService.java`: 添加 `resolveEntityType` 接口方法
- `BpmOAAttachmentServiceImpl.java`: 实现类型解析和优化反射调用
- `BpmProcessInstanceController.java`: 简化Controller逻辑移除业务逻辑
### 5. 技术收益
- ✅ 更清晰的分层架构
- ✅ 统一的反射调用机制
- ✅ 更好的错误处理和日志记录
- ✅ 代码复用性提升
## 验证要点
1. 确保配置表中存在对应的流程映射配置
2. 验证实体类和Mapper类路径正确
3. 测试异常情况的错误处理和日志记录
4. 确认ReflectionInvoker正确处理代理类和方法调用