
- 新增分片上传相关接口和 VO 类 - 实现分片上传服务,包括初始化、获取预签名 URL、完成上传和取消上传 - 添加分片上传会话的数据库表结构和 Mapper - 优化错误处理和参数验证
5.2 KiB
5.2 KiB
流程附件上传机制优化
任务概述
将 BpmProcessInstanceController.uploadAttachment
方法从硬编码映射改为通过配置表动态获取实体类和Mapper类,与 ProcessQueryServiceImpl
保持一致的反射机制。
实施方案
方案1:完全使用配置表机制(已采用)
- 移除硬编码的
entityTypeMap
- 注入
ProcessMappingConfigService
- 修改
resolveEntityType
方法通过配置表动态获取类信息 - 参数兼容:
processType
映射到processCode
具体修改
1. 移除硬编码机制
// 删除了以下内容:
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. 新增依赖注入
@Resource
private ProcessMappingConfigService processMappingConfigService;
3. 重构解析方法
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语句
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接口全限定名
使用示例
前端调用方式保持不变:
{
"processType": "oa_reimbursement", // 会作为processCode查询配置表
"processBusinessId": 123,
"fileItems": [...]
}
后台会自动:
- 根据
processType="oa_reimbursement"
查询配置表 - 获取对应的实体类和Mapper类
- 动态实例化并调用附件更新服务
执行时间
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. 技术收益
- ✅ 更清晰的分层架构
- ✅ 统一的反射调用机制
- ✅ 更好的错误处理和日志记录
- ✅ 代码复用性提升
验证要点
- 确保配置表中存在对应的流程映射配置
- 验证实体类和Mapper类路径正确
- 测试异常情况的错误处理和日志记录
- 确认ReflectionInvoker正确处理代理类和方法调用