当前位置: 首页 > news >正文

别再只会用Assignee了!用Activiti7多实例搞定会签与或签的完整配置流程

Activiti7多实例实战:从会签到或签的进阶审批配置指南

当审批流程从单人决策转向集体决策时,工作流引擎的配置复杂度会呈指数级上升。想象这样一个场景:某跨国企业的采购申请需要经过三个区域负责人的联合审批,其中任意两位同意即可生效;或者紧急报销流程只需获得财务部门任意一位主管的批准就能进入下一环节。这类需求在Activiti7中可以通过多实例任务(Multi-Instance Task)优雅实现,但90%的中级开发者都会在Completion Condition表达式或Collection变量传递环节踩坑。

1. 多实例任务的核心架构解析

多实例任务本质上是BPMN 2.0规范中的一种特殊活动类型,它允许单个任务节点在运行时动态创建多个实例。与简单的Assignee分配不同,这种机制为复杂审批场景提供了三种关键控制维度:

执行模式选择

  • 顺序执行(Sequential=true):适用于需要层级审批的场景,如先部门经理后总监
  • 并行执行(Sequential=false):适用于同级多人同时审批,如委员会投票

参与者配置矩阵

配置项作用域示例值注意事项
Collection流程变量${approveUserList}必须实现java.util.List接口
Element Variable元素变量member与Assignee表达式保持一致
Loop Cardinality固定数量3与Collection互斥

完成条件的三层控制体系

  1. 数量阈值${nrOfCompletedInstances >= 2}
  2. 比例控制${nrOfCompletedInstances/nrOfInstances > 0.6}
  3. 自定义逻辑:通过DelegateExecution注入业务判断
// Spring Boot中的多实例流程启动示例 @RestController @RequestMapping("/process") public class MultiInstanceController { @Autowired private RuntimeService runtimeService; @PostMapping("/start") public String startProcess(@RequestBody ApproveRequest request) { Map<String, Object> variables = new HashMap<>(); variables.put("approveUserList", request.getApprovers()); variables.put("minApproves", request.getMinApproves()); ProcessInstance instance = runtimeService.startProcessInstanceByKey( "multiInstanceProcess", variables ); return instance.getId(); } }

2. 会签模式的深度配置实战

会签(即"与签")是多人必须全部或部分完成审批才能使流程继续的典型场景。某电商平台的退款审核系统曾因错误配置导致2000多笔订单卡在审批环节,根本原因正是Completion Condition表达式与业务规则不匹配。

比例通过型会签的黄金配置法则

  1. 在BPMN设计器中设置Multi-Instance类型为Parallel
  2. Collection填写流程变量名如${approveUserList}
  3. Completion Condition填入比例公式:
    ${nrOfCompletedInstances/nrOfInstances >= 0.7}

动态阈值实现方案

<multiInstanceLoopCharacteristics isSequential="false" activiti:collection="${approveUserList}" activiti:elementVariable="approver"> <completionCondition>${nrOfCompletedInstances >= minApproves}</completionCondition> </multiInstanceLoopCharacteristics>

审批结果聚合的三种模式对比

  1. 乐观模式(任一通过):

    # 历史任务记录示例 SELECT * FROM act_hi_taskinst WHERE PROC_INST_ID_ = '1001' AND DELETE_REASON_ IS NULL;
  2. 悲观模式(全员通过):

    // 在DelegateTask中校验历史审批结果 List<HistoricTaskInstance> histories = historyService .createHistoricTaskInstanceQuery() .processInstanceId(execution.getProcessInstanceId()) .list(); long rejects = histories.stream() .filter(h -> "REJECT".equals(h.getVariable("result"))) .count(); if(rejects > 0) { execution.setVariable("approved", false); }
  3. 混合模式(自定义规则):

    -- 数据库级别验证(Oracle示例) SELECT SUM(CASE WHEN VAR_TEXT_ = 'APPROVE' THEN 1 ELSE 0 END) approves, COUNT(*) total FROM ACT_HI_VARINST WHERE PROC_INST_ID_ = '1001' AND NAME_ = 'approvalResult'

3. 或签模式的特殊处理技巧

或签(即"或签")的特点是任一处理人完成操作即可推动流程,但实际业务中往往需要区分"通过"和"拒绝"两种操作结果。某金融机构的贷款审批系统就曾因未处理拒绝场景导致错误放款。

基础或签配置

Completion Condition: ${nrOfCompletedInstances >= 1}

增强型或签实现方案

  1. 在任务完成时注入决策结果:

    taskService.complete(taskId, Variables.putValue("decision", "REJECT") );
  2. 配置边界事件捕获拒绝:

    <boundaryEvent id="rejectEvent" attachedToRef="approvalTask"> <messageEventDefinition messageRef="rejectMsg" /> </boundaryEvent>
  3. 使用执行监听器清理残余实例:

    public class CancelInstancesListener implements ExecutionListener { @Override public void notify(DelegateExecution execution) { runtimeService.createExecutionQuery() .activityId("approvalTask") .list() .forEach(e -> runtimeService.deleteExecution(e.getId())); } }

或签场景下的数据一致性挑战

  • ACT_RU_TASK表:未完成任务需手动清理
  • ACT_HI_TASKINST表:通过DELETE_REASON_字段区分自然完成与强制终止
  • 业务数据同步:建议采用SAGA模式补偿事务

4. 生产环境中的性能优化策略

当审批人员规模超过50人时,原生多实例实现可能遇到性能瓶颈。某政务审批平台在接入300+部门时,流程实例启动时间达到了不可接受的8秒。

索引优化方案

-- MySQL性能优化示例 ALTER TABLE ACT_RU_IDENTITYLINK ADD INDEX idx_task_assignee (TASK_ID_, TYPE_, USER_ID_); ALTER TABLE ACT_RU_VARIABLE ADD INDEX idx_proc_inst_name (PROC_INST_ID_, NAME_);

批量处理模式

// 使用Bulk API处理大规模审批人 List<String> approvers = getHugeApproverList(); // 500+人 runtimeService.createProcessInstanceBuilder() .processDefinitionKey("massApproval") .variable("approveUserList", approvers) .variable("batchSize", 100) .addExtensionElement(new BatchConfigElement()) .executeAsync();

缓存层设计要点

  1. 使用Redis缓存流程定义:

    # application.yml配置 activiti: process-definition-cache: enabled: true max-size: 1000 expire-after-write: 1h
  2. 审批人列表分片加载:

    @Cacheable(value = "approvers", key = "#deptId") public List<String> getDepartmentApprovers(String deptId) { // 数据库查询 }
  3. 历史决策结果预加载:

    /* MyBatis映射示例 */ <select id="getApprovalTrend" resultType="ApprovalStat"> SELECT APPROVER, COUNT(*) total FROM BIZ_APPROVAL_HISTORY WHERE PROCESS_DEF_ID = #{defId} GROUP BY APPROVER </select>

在大型制造业集团的采购系统中,通过组合使用这些优化策略,成功将200人规模的会签流程实例启动时间从12秒降低到1.8秒,任务分配耗时从5秒降至400毫秒。关键点在于:提前识别Collection变量的数据规模,对超百人场景采用分批加载机制;对高频使用的流程定义启用二级缓存;在历史数据查询上建立适当的索引策略。

http://www.rkmt.cn/news/1483550.html

相关文章:

  • 从输入法到语音识别:聊聊马尔可夫链在我们身边的那些“隐形”应用
  • Nginx黑白名单进阶玩法:告别手动配置,用Lua+Redis实现动态封禁恶意IP
  • 深度解析10款降AIGC工具:帮你锁定达标神器
  • 别再混淆了!一文讲清SAP WM里SU、HU和Quant的区别与联系(含配置点检查)
  • Gunicorn:Python WSGI HTTP 服务器
  • 好用的 GEO 优化线上推广品牌哪家强 - mypinpai
  • GPU显存稳定性测试终极指南:6分钟发现隐藏硬件故障
  • Foreman:服务器生命周期管理
  • SuperMap iDesktop实战:当CAD数据没有坐标系信息时,如何一步步完成投影转换?
  • 告别Electron?我用Flutter 3.0给Windows 11开发了个不到20MB的桌面应用
  • Randall-Sundrum膜世界中的虫洞与黑洞弦解
  • 2026年电话机器人选型指南:不同预算下的性价比推荐方案
  • Java Swing中JTable单元格添加可点击按钮的完整实现方案
  • 别再乱铺地了!PCB差分线设计的3个常见误区与实战避坑指南(以USB3.0为例)
  • 鸿蒙原生应用进阶:全面彻底吃透 Scroll 与 NestedScroll 嵌套滚动机制及滑动冲突解决方案
  • yuzu模拟器:如何在电脑上免费畅玩Switch游戏的完整指南
  • Blender:开源3D创作套件,18.4k Star
  • 3步免费解锁Wand专业版:本地增强工具的完整使用指南
  • PXA255嵌入式系统CF卡启动专用EBOOT源码包(含完整驱动与编译脚本)
  • 量子测量中的上下文无关性与相空间重构技术
  • 从JavaScript的0.1+0.2≠0.3说起:手把手图解IEEE754舍入模式与精度陷阱
  • 2026年台州代理记账选对助企业行稳致远 蓝图财税专业推荐 - 本地品牌推荐
  • 从‘极值理论’到‘开集识别’:一篇讲透OpenMax背后的数学原理与工程实现
  • AI写作辅助网站的合规使用指南:如何让AI生成内容通过严格学术审查
  • 职场录音转写工具投入产出比实测:随身鹿、通义听悟、阿里云与Trint该怎么选?
  • 外贸B2B建站系统推荐:2026年最新测评
  • 告别臃肿客户端:用Oracle Instant Client + Navicat 16 轻量连接远程数据库
  • 别再死记硬背了!用Arduino框架和Adafruit库5分钟搞定ESP32的I2C通讯
  • 终极指南:3分钟为网易云音乐安装BetterNCM插件管理器
  • ESP32项目美化:用Img2Lcd和PCtoLCD给你的OLED屏加上Logo和图片(含省内存技巧)