审批流程系统设计与实现:状态驱动、灵活扩展的企业级解决方案

发布于:2025-08-15 ⋅ 阅读:(9) ⋅ 点赞:(0)

审批流程系统设计与实现:状态驱动、灵活扩展的企业级解决方案

本文基于实际企业级审批系统源码,深入解析如何设计高扩展性、强一致性的审批流程引擎,涵盖状态机设计、多租户隔离、文件服务集成等核心实现。

1. 系统设计概览

审批系统的核心架构分为三大模块:

  • 公共模块:枚举定义、DTO对象、基础转换器
  • 审批模块:流程引擎核心实现、模板管理
  • 业务模块:具体业务审批处理器

2. 公共模块设计精要

2.1 状态枚举设计

通过枚举实现状态机是审批系统的核心设计模式:

// 业务流程状态机
public enum ApprovalStatus {
    PENDING("待提交"),
    SUBMITTED("已提交"),
    APPROVED("审批通过"),
    REJECTED("拒绝"),
    WITHDRAW("撤回");
}

// 流程执行状态
public enum ProcessStatus {
    IN_PROGRESS("处理中"),
    APPROVED("通过"),
    REJECTED("拒绝"),
    WITHDRAW("撤回");
}

// 审批模式
public enum ApprovalMode {
    SERIAL,  // 串签:顺序审批
    PARALLEL // 会签:并行审批
}

设计亮点

  • 使用@Schema注解实现OpenAPI文档自动生成
  • 通过description字段支持多语言扩展
  • 严格区分流程状态与业务状态
2.2 DTO对象设计

数据传输对象实现分层解耦:

// 审批流程DTO
public class ApprovalProcessDTO {
    private Long id;
    private int currentStep; // 当前步骤
    private ProcessStatus processStatus;
    private List<ApprovalStepDTO> approvalStepDTOList; // 步骤树
}

// 审批步骤DTO
public class ApprovalStepDTO {
    private Integer stepOrder;
    private StepStatus stepStatus;
    private ApprovalMode approvalMode; 
    private List<ApproverDTO> approverDTOList; // 审批人列表
}

分层结构

BusinessDTO 
  └── ApprovalProcessDTO
        └── ApprovalStepDTO
             └── ApproverDTO

3. 审批流程引擎核心实现

3.1 状态机流转逻辑
PENDING:
创建流程
PENDING
SUBMITTED:
提交
SUBMITTED
IN_PROGRESS:
启动审批
IN_PROGRESS
APPROVED:
最后一步通过
REJECTED:
任意步骤拒绝
APPROVED
REJECTED
WITHDRAW:
用户撤回
3.2 多模式审批处理

会签(Parallel)模式处理逻辑

// ApprovalProcessService.java
private void checkStepCompletion(ApprovalStep step, 
                                ApprovalProcess process, 
                                ApprovalStatus currentStatus) {
    if (step.getApprovalMode() == ApprovalMode.PARALLEL) {
        // 会签模式:任一拒绝即整体拒绝
        boolean anyRejected = approverList.stream()
            .anyMatch(a -> a.getStatus() == ApproverStatus.REJECTED);
            
        if (anyRejected) {
            rejectProcess(process); // 触发流程拒绝
        } 
        // 所有审批人通过才进入下一步
        else if (allApproved(approverList)) {
            moveToNextStep(process);
        }
    }
}

串签(Serial)模式处理逻辑

private void moveToNextApproverOrStep(ApprovalStep step, ApprovalProcess process) {
    if (step.getApprovalMode() == ApprovalMode.SERIAL) {
        // 查找下一个待处理审批人
        Optional<ApprovalStepApprover> nextApprover = approverRepository
            .findFirstByStepIdAndStatusOrderById(step.getId(), ApproverStatus.PENDING);
            
        if (nextApprover.isPresent()) return; // 不移动步骤
    }
    moveToNextStep(process); // 移动到下一步
}

4. 文件服务深度集成

4.1 文件关联设计
@Entity
public class ApprovalStepApprover {
    @Id
    private Long id;
    
    // 通过approverId关联文件
    private String approverId; 
}

@Entity
public class BaseFile {
    private String approverId; // 关联审批人
    private String objectName; // MinIO存储标识
}
4.2 文件操作服务
@Service
public class MinioService {
    // 生成唯一存储路径
    private String generateObjectName(String suffix) {
        return "approval/" + UUID.randomUUID() + "." + suffix;
    }
    
    // 上传并关联审批人
    public void uploadFile(String objectName, MultipartFile file) {
        minioClient.putObject(
            PutObjectArgs.builder()
                .bucket(bucketName)
                .object(objectName)
                .stream(file.getInputStream(), file.getSize(), -1)
                .build()
        );
    }
    
    // 生成临时访问链接
    public String getPresignedUrl(String objectName) {
        return minioClient.getPresignedObjectUrl(
            GetPresignedObjectUrlArgs.builder()
                .bucket(bucketName)
                .object(objectName)
                .expiry(3600) // 1小时有效
                .build()
        );
    }
}

5. 扩展性设计

5.1 业务处理器注册机制
@Service
public class ApprovalProcessService {
    private final Map<BusinessType, Consumer<FinishApprovalDTO>> approvalHandlers;
    
    @PostConstruct
    void initHandlers() {
        // 注册原油业务处理器
        EnumSet.of(
            BusinessType.CRUDE_OIL_PURCHASE_CONFIRM_ORDER,
            BusinessType.CRUDE_OIL_PURCHASE_PLAN
        ).forEach(type -> 
            approvalHandlers.put(type, crudeOilMngClient::finishApproval)
        );
        
        // 注册原材料业务处理器
        approvalHandlers.put(
            BusinessType.RAW_MATERIAL_PROCUREMENT_PLAN, 
            rawMaterialMngClient::finishApproval
        );
    }
    
    private void finishApproval(FinishApprovalDTO dto) {
        approvalHandlers.get(dto.getBusinessType())
                       .accept(dto);
    }
}
5.2 新增业务接入步骤
  1. BusinessType枚举中添加新业务类型
  2. 实现ApprovalHandler接口
@Component
public class NewBusinessHandler implements ApprovalHandler {
    @Override
    public BusinessType getSupportedType() {
        return BusinessType.NEW_BUSINESS;
    }
    
    @Override
    public void handleApproval(Long businessId, ApprovalStatus status) {
        // 实现业务状态更新逻辑
    }
}
  1. FinishApprovalService中自动注册处理器

6. 性能优化实践

6.1 审批流程保存优化
// 批量保存优化:减少DB交互
private List<ApprovalStepDTO> saveSteps(Long processId, 
                                        List<ApprovalStepDTO> stepDTOs) {
    
    // 批量保存步骤
    List<ApprovalStep> steps = stepRepository.saveAll(
        stepDTOs.stream()
            .map(dto -> {
                ApprovalStep step = new ApprovalStep();
                step.setProcessId(processId);
                return step;
            })
            .collect(Collectors.toList())
    );
    
    // 批量保存审批人
    List<ApprovalStepApprover> approvers = new ArrayList<>();
    steps.forEach(step -> {
        stepDTOs.get(step.getStepOrder()-1)
            .getApproverDTOList()
            .forEach(approverDTO -> {
                ApprovalStepApprover a = new ApprovalStepApprover();
                a.setStepId(step.getId());
                approvers.add(a);
            });
    });
    approverRepository.saveAll(approvers);
    
    return convertToDTOs(steps);
}
6.2 文件清理任务
@Scheduled(cron = "0 0 2 * * ?") // 每天凌晨2点执行
public void clearOrphanFiles() {
    List<BaseFile> orphans = baseFileRepository.findOrphanFiles();
    List<String> objectNames = orphans.stream()
        .map(BaseFile::getObjectName)
        .collect(Collectors.toList());
        
    minioService.removeFiles(objectNames); // 批量删除
    baseFileRepository.deleteAll(orphans);
}

7. 关键设计决策总结

设计选择 优势 应用场景
枚举状态机 编译时检查、杜绝无效状态 流程状态管理
DTO分层结构 解耦持久层与展示层 API接口设计
审批模式策略 灵活支持不同审批场景 会签/串签流程
处理器注册机制 开闭原则支持扩展 新增业务审批
文件元数据分离 独立管理存储资源 附件管理

最佳实践建议

  1. 状态驱动开发:所有业务逻辑围绕状态流转实现
  2. 防腐层设计:通过DTO隔离领域模型与接口模型
  3. 幂等性保证:审批操作需支持重复提交
  4. 事件溯源:关键状态变更记录审计日志
  5. 资源隔离:按业务类型隔离审批流程实例

完整实现源码将托管至unknown:TODO

通过本文展示的审批系统设计,开发者可快速构建支持复杂业务流程的企业级审批引擎,其模块化设计和扩展机制能满足各类业务场景的审批需求。


网站公告

今日签到

点亮在社区的每一天
去签到