Flowable实战:如何用会签模式搞定多人审批流程(附BPMN配置截图)

📅 发布时间:2026/7/12 14:55:32 👁️ 浏览次数:
Flowable实战:如何用会签模式搞定多人审批流程(附BPMN配置截图)
Flowable实战多人审批流程的会签模式深度解析与配置指南在企业的日常运营中审批流程无处不在。无论是合同盖章、费用报销还是项目立项常常需要多位负责人点头才能放行。过去这类流程要么依赖纸质单据的物理流转要么在OA系统中留下混乱的审批记录效率低下且难以追踪。如今借助像Flowable这样的流程引擎我们可以将这些复杂的协作逻辑清晰地建模、自动化执行。其中会签模式是处理“多人审批”场景的利器它允许你将一个任务分发给多个参与者并定义明确的完成规则。但很多开发者在初次接触时往往会卡在几个关键点上如何动态地确定哪些人需要参与是让他们一个一个审还是一起审审批结果如何汇总并驱动流程走向本文将从一个真实的报销审批场景切入手把手带你拆解Flowable中会签任务的配置逻辑分享实战中的设计策略与避坑经验并提供可直接复用的BPMN配置思路。1. 理解会签不仅仅是“多人任务”会签在Flowable的语境下特指多实例用户任务。它的核心思想是将一个用户任务复制成多个实例每个实例分配给列表中的一位参与者。只有当这些实例按照预设的规则如全部完成、多数同意等处理完毕后整个会签任务才算完成流程才能继续。1.1 会签与常见审批模式辨析在深入配置之前我们先厘清几个容易混淆的概念会签 vs. 或签这是最常被对比的一对。会签要求所有或指定数量的参与者完成任务而或签通常通过包容网关实现是指流程会根据条件进入一个或多个分支路径这些路径上的任务可能由不同的人处理但并非针对同一任务的多人副本。会签 vs. 并行网关并行网关拆分出的是完全独立、不同性质的任务流比如同时进行“开发编码”和“撰写文档”。会签创建的是同一性质任务的多个副本比如“审批报销单”这个动作由张三、李四、王五分别执行。理解这些区别有助于你在设计流程时做出正确选择。会签的核心是“对同一事项的集体决策”。1.2 顺序执行与并行执行的策略选择会签支持两种执行模式选择哪一种对流程体验和耗时影响巨大。执行模式BPMN属性工作方式适用场景潜在考量顺序执行sequentialtrue参与者按列表顺序依次审批。前一人完成后任务才流转给下一人。1. 审批存在明确的层级或依赖关系如先直属领导再部门总监。2. 希望避免后续审批者受到前面审批意见的干扰。3. 业务上要求严格的逐级审批。流程总耗时等于各参与者处理时间的总和可能成为效率瓶颈。并行执行sequentialfalse所有参与者同时收到审批任务可独立、同时处理。1. 审批者之间地位平等无先后依赖如项目组内多位专家评审。2. 追求审批效率最大化。3. 审批意见相对独立可并行收集。可能出现意见冲突需要更明确的“完成条件”来裁决如“超过半数同意即可”。提示在实际项目中我常常发现团队会默认选择并行会签以求“快”但忽略了业务上隐性的顺序要求。例如一份采购合同法务审核可能必须发生在财务审核之前因为合同条款直接影响预算。这时顺序会签或拆分成两个独立任务更合适。2. 实战配置构建一个动态的报销会签审批节点假设我们有一个员工报销流程金额超过5000元时需要其部门经理、项目负责人和财务专员三人共同审批会签。我们将以此为例展示从定义到实现的完整步骤。2.1 BPMN 2.0 XML 核心配置拆解在Flowable设计器如Eclipse插件或Flowable Modeler中拖入一个“用户任务”然后将其转换为多实例。背后的BPMN XML代码是关键userTask idmultiInstanceApproval name高管会签审批 flowable:assignee${assignee} multiInstanceLoopCharacteristics isSequentialfalse flowable:collection${approverList} flowable:elementVariableassignee completionCondition${nrOfCompletedInstances nrOfInstances}/completionCondition /multiInstanceLoopCharacteristics /userTask让我们逐行解析这个配置块userTask定义了基础的用户任务。flowable:assignee${assignee}是关键这意味着每个任务实例的办理人将由变量assignee动态决定。multiInstanceLoopCharacteristics这是声明多实例即会签的标签。isSequentialfalse指定为并行执行。flowable:collection${approverList}这是会签的灵魂。它指定了一个名为approverList的流程变量引擎会遍历这个集合来创建任务实例。这个列表必须是java.util.List或数组类型。flowable:elementVariableassignee在每次遍历中集合的当前元素会被赋值给assignee变量从而传递给上面的用户任务。completionCondition完成条件。${nrOfCompletedInstances nrOfInstances}是默认条件表示所有实例都完成时会签任务才整体完成。nrOfCompletedInstances和nrOfInstances是Flowable自动为多实例任务创建的内置变量。2.2 动态参与者列表的生成策略如何设置approverList这个变量这是实现动态会签的核心。通常有以下几种方式在启动流程时传入如果审批人名单在流程发起时就已确定可以在调用RuntimeService.startProcessInstanceById方法时将列表作为流程变量传入。ListString approvers Arrays.asList(manager_zhang, lead_li, finance_wang); MapString, Object variables new HashMap(); variables.put(approverList, approvers); runtimeService.startProcessInstanceById(processDefinitionId, businessKey, variables);通过前序任务的计算设置更常见的场景是审批人需要根据业务规则动态计算。例如可以在会签任务之前设置一个“自动任务”Service Task在其中执行Java代码或调用表达式计算出审批人列表并设置到流程变量中。serviceTask idcalculateApprovers name计算审批人 flowable:delegateExpression${calculateApproversDelegate} /对应的Java委托类public class CalculateApproversDelegate implements JavaDelegate { Override public void execute(DelegateExecution execution) { String applicantDept (String) execution.getVariable(department); Double amount (Double) execution.getVariable(amount); ListString approverList new ArrayList(); // 根据部门和金额等业务规则动态查询或计算审批人 approverList.addAll(departmentService.getManagers(applicantDept)); if (amount 10000) { approverList.addAll(financeService.getSeniorApprovers()); } execution.setVariable(approverList, approverList); } }使用监听器注入可以在任务创建事件上附加监听器动态地为该任务实例添加候选人。注意确保approverList变量在会签任务开始执行之前就已经存在于流程上下文中否则引擎会抛出异常。我建议在流程设计图上明确标出该变量的设置点便于维护。3. 超越默认高级完成条件与结果聚合默认的“全部完成”条件可能不符合所有业务场景。比如三人会签两人同意即可通过或者一票否决。这就需要自定义完成条件。3.1 自定义完成条件表达式修改completionCondition中的表达式即可实现复杂逻辑。这通常需要结合每个审批实例产生的输出变量。假设每个审批者完成任务时会设置一个本地变量approvalResult值为true表示同意false表示拒绝。我们可以在会签任务上定义聚合逻辑completionCondition ${nrOfCompletedInstances 2 nrOfApproved 2} /completionCondition但这里有个问题nrOfApproved不是内置变量我们需要在流程级别进行累加。一种常见做法是在每个审批任务完成时通过任务完成监听器来更新流程级别的计数器变量。3.2 通过监听器实现投票统计为会签中的每个用户任务添加一个执行监听器监听complete事件。userTask idmultiInstanceApproval name高管会签审批 flowable:assignee${assignee} extensionElements flowable:executionListener eventcomplete delegateExpression${voteAggregationListener}/flowable:executionListener /extensionElements ... !-- 多实例配置 -- /userTask实现监听器汇总投票结果public class VoteAggregationListener implements ExecutionListener { Override public void notify(DelegateExecution execution) { // 获取当前任务实例的审批结果 Boolean localResult (Boolean) execution.getVariableLocal(approvalResult); // 获取或初始化流程级别的统计变量 Integer approvedCount (Integer) execution.getVariable(approvedCount); Integer rejectedCount (Integer) execution.getVariable(rejectedCount); if (approvedCount null) approvedCount 0; if (rejectedCount null) rejectedCount 0; // 根据当前结果更新计数 if (Boolean.TRUE.equals(localResult)) { approvedCount; } else { rejectedCount; } // 存回流程变量 execution.setVariable(approvedCount, approvedCount); execution.setVariable(rejectedCount, rejectedCount); // 可以在这里根据计数判断是否提前满足完成条件复杂场景 } }在完成条件中使用这些聚合变量completionCondition !-- 全部同意或有一票否决则提前结束模拟一票否决 -- ${nrOfCompletedInstances nrOfInstances || rejectedCount 0} /completionCondition或者实现“多数同意”completionCondition !-- 超过半数同意即通过 -- ${approvedCount nrOfInstances / 2} /completionCondition3.3 会签结束后的流程路由会签任务完成后我们往往需要根据汇总的结果来决定流程走向。例如全部同意则进入“付款”环节有人拒绝则进入“打回修改”环节。这通常在会签任务后接一个排他网关来实现。网关的条件表达式可以基于我们之前聚合的流程变量如approvedCount,rejectedCount或一个最终计算出的结果变量如finalDecision来判断。exclusiveGateway iddecisionAfterMultiInstance / sequenceFlow idflowToPay sourceRefdecisionAfterMultiInstance targetRefpaymentTask conditionExpression xsi:typetFormalExpression !-- 假设最终决策变量已设置为approved -- ${finalDecision approved} /conditionExpression /sequenceFlow sequenceFlow idflowToReject sourceRefdecisionAfterMultiInstance targetRefmodifyTask conditionExpression xsi:typetFormalExpression ${finalDecision rejected} /conditionExpression /sequenceFlow4. 性能优化与常见问题排查当会签参与者数量很大比如数十人时需要注意性能问题。数据库事务并行会签会产生大量并行的用户任务每个任务的创建、完成都是数据库操作。确保数据库连接池配置合理并关注长事务风险。历史数据膨胀Flowable会为每个任务实例保存详细的历史记录。如果参与者列表非常大可以考虑调整历史级别如从full改为activity或在流程定义级别进行归档清理。异步执行对于极其耗时的会签任务如每个审批都需要外部系统调用可以考虑将多实例任务本身配置为异步的避免阻塞流程引擎线程。常见问题排查清单任务实例没有创建首先检查approverList变量是否在正确的作用域流程实例且不为空。使用Flowable Admin应用或历史服务查询流程变量进行验证。完成条件不生效检查表达式语法是否正确引用的变量名是否准确。内置变量nrOfCompletedInstances和nrOfInstances是整数类型。并行会签中某人审批后任务消失这是正常现象。在并行模式下每个参与者只看到并完成自己的那个任务实例。当他完成后他的任务列表里这个任务就消失了但会签整体并未结束直到满足完成条件。顺序会签卡住检查前一个任务实例是否已真正“完成”调用了TaskService.complete并且流程已流转。同时确认参与者列表顺序是否符合预期。配置会签模式本质上是将现实世界中模糊的集体协作规则用精确的、可执行的模型定义出来。从简单的“全部同意”到复杂的“加权投票”、“一票否决”Flowable的多实例机制提供了足够灵活的扩展点。关键在于你需要清晰地理解业务规则并将其转化为对collection、completionCondition和监听器的恰当运用。在项目实践中我习惯为每个复杂的会签节点编写一个简明的设计文档说明参与者来源、执行模式和完成规则这能极大减少后续维护的沟通成本。