别再写死审批人了!用Activiti7多实例搞定会签与或签,附SpringBoot完整代码

别再写死审批人了!用Activiti7多实例搞定会签与或签,附SpringBoot完整代码 动态审批人实践Activiti7多实例在SpringBoot中的工程化落地审批流程中写死审批人列表是许多开发团队在初期快速实现工作流时常见的做法但随着业务复杂度提升这种硬编码方式会带来诸多问题审批人变动需要重新部署流程、无法适应组织架构调整、难以支持跨部门协作场景。本文将深入探讨如何利用Activiti7的多实例特性在SpringBoot项目中实现真正动态化的会签与或签审批。1. 动态审批人架构设计在传统审批流程中审批人通常直接在BPMN图中通过固定ID指定。这种设计存在明显局限性变更成本高每次人员调整都需要修改流程定义并重新部署缺乏灵活性无法根据业务条件动态调整审批链条难以维护当流程版本迭代时审批人配置容易遗漏现代企业级应用更倾向于采用动态审批人模式其核心优势在于运行时决策审批人列表在流程实例启动时确定外部系统集成可从HR系统、组织架构或业务规则引擎获取弹性扩展支持中途调整审批人而不中断流程实现动态多实例审批需要解决三个关键问题数据来源审批人列表的获取渠道与更新机制变量传递如何在流程实例中注入动态集合状态同步审批人变更时的流程实例调整策略2. SpringBoot集成实战2.1 基础环境配置首先确保项目中已正确引入Activiti7和SpringBoot Starter依赖dependency groupIdorg.activiti/groupId artifactIdactiviti-spring-boot-starter/artifactId version7.1.0.M6/version /dependency创建基础的请假流程BPMN文件时需要特别关注多实例任务的配置userTask idmultiInstanceTask name会签审批 activiti:assignee${currentApprover} multiInstanceLoopCharacteristics activiti:elementVariablecurrentApprover activiti:collection${approveUserList} activiti:isSequentialfalse completionCondition${nrOfCompletedInstances/nrOfInstances 0.5}/completionCondition /multiInstanceLoopCharacteristics /userTask关键参数说明参数说明示例值elementVariable当前审批人变量名currentApprovercollection审批人集合表达式approveUserListisSequential是否顺序审批false(并行)completionCondition完成条件表达式见示例2.2 动态审批人注入在流程启动时通过RuntimeService注入从外部系统获取的审批人列表Service public class LeaveProcessService { Autowired private RuntimeService runtimeService; Autowired private UserServiceClient userServiceClient; public String startLeaveProcess(LeaveRequest request) { // 从组织架构服务获取审批链 ListString approvers userServiceClient.getApprovers( request.getApplicantId(), request.getLeaveType(), request.getDuration() ); MapString, Object variables new HashMap(); variables.put(approveUserList, approvers); variables.put(leaveRequest, request); ProcessInstance instance runtimeService.startProcessInstanceByKey( leaveApproval, variables ); return instance.getId(); } }提示建议将审批人获取逻辑封装为独立服务便于统一处理缓存、降级等场景3. 高级场景处理3.1 审批人中途变更实际业务中经常遇到审批人离职或岗位调整的情况此时需要动态更新审批任务。实现方案包括任务重分配APItaskService.setAssignee(taskId, newAssignee);批量更新策略ListTask tasks taskService.createTaskQuery() .processInstanceId(processInstanceId) .list(); tasks.forEach(task - { if(needReassign(task.getAssignee())) { String newApprover findReplacement(task.getAssignee()); taskService.setAssignee(task.getId(), newApprover); } });监听器自动处理Component public class TaskReassignListener implements TaskListener { Override public void notify(DelegateTask delegateTask) { if(isUserInactive(delegateTask.getAssignee())) { delegateTask.setAssignee(findActiveUser(delegateTask.getAssignee())); } } }3.2 混合审批模式复杂业务流程可能需要组合使用会签和或签sequenceFlow idflow1 sourceRefstart targetReforSignTask/ userTask idorSignTask name部门审批 activiti:assignee${deptApprover} multiInstanceLoopCharacteristics activiti:collection${deptApprovers} activiti:elementVariabledeptApprover completionCondition${nrOfCompletedInstances 1}/completionCondition /multiInstanceLoopCharacteristics /userTask sequenceFlow idflow2 sourceReforSignTask targetRefgroupSignTask/ userTask idgroupSignTask name委员会评审 activiti:assignee${committeeMember} multiInstanceLoopCharacteristics activiti:collection${committeeMembers} activiti:elementVariablecommitteeMember completionCondition${nrOfCompletedInstances/nrOfInstances 0.7}/completionCondition /multiInstanceLoopCharacteristics /userTask4. 性能优化与监控当审批人规模较大时需特别注意性能问题批量任务查询优化ListTask tasks taskService.createTaskQuery() .processInstanceId(processInstanceId) .initializeFormKeys() // 预初始化表单键 .taskUnassigned() // 只查询未分配任务 .listPage(0, 100); // 分页处理审批进度监控接口GetMapping(/progress/{processInstanceId}) public ApprovalProgress getProgress(PathVariable String processInstanceId) { Long total runtimeService.getVariable(processInstanceId, nrOfInstances); Long completed runtimeService.getVariable(processInstanceId, nrOfCompletedInstances); return new ApprovalProgress( total, completed, total - completed, (double)completed / total ); }历史数据归档策略-- 定期归档已完成任务数据 INSERT INTO ARCHIVED_TASKS SELECT * FROM ACT_HI_TASKINST WHERE END_TIME_ IS NOT NULL AND END_TIME_ DATEADD(month, -3, GETDATE()); DELETE FROM ACT_HI_TASKINST WHERE END_TIME_ IS NOT NULL AND END_TIME_ DATEADD(month, -3, GETDATE());在大型金融项目的流程引擎升级中采用动态审批人模式后流程变更部署次数减少了83%审批链调整平均耗时从原来的2天缩短至30分钟内完成。特别是在矩阵式管理的组织中能够灵活适应双线汇报场景审批通过率提升了17%。