Flowable(以及之前的 Activiti)作为强大的 BPMN 2.0 流程引擎,其核心流程控制模式是构建复杂业务流程的基石。 会签、或签、分支、并行这四种模式确实是设计和实现流程逻辑的关键。下面详细解析它们的概念、实现方式、配置要点和区别:
1. 会签 (Multi-Instance Sequential / Parallel - All Required
)
- 概念: 一个任务需要多个参与者(通常指人)共同处理,并且所有参与者都必须完成该任务(或达到特定完成条件),流程才能继续向下流转。例如:部门预算需要财务部、市场部、技术部三位经理全部审批通过。
- BPMN 实现: 使用多实例任务 (
Multi-Instance Task
),通常是用户任务 (User Task
)。 - 关键配置:
- 多实例类型:
Parallel
(参与者可同时处理) 或Sequential
(参与者按顺序处理,较少见)。 - 实例集合: 指定参与者的集合变量 (如
assigneeList
)。集合元素可以是用户 ID、组 ID 或候选人。 - 元素变量: 为每个实例迭代时使用的临时变量名 (如
assignee
),用于动态分配任务处理人 (${assignee}
)。 - 完成条件:
- 默认:
nrOfInstances == nrOfCompletedInstances
(所有实例完成)。 - 自定义表达式: 可定义更复杂的条件 (如
nrOfCompletedInstances >= 2
),但严格意义上的“会签”通常要求全部完成。
- 默认:
- 多实例类型:
- XML 片段示例:
<userTask id="multiApprovalTask" name="会签审批"> <multiInstanceLoopCharacteristics isSequential="false" flowable:collection="${assigneeList}" flowable:elementVariable="assignee"> <completionCondition>${nrOfInstances == nrOfCompletedInstances}</completionCondition> <!-- 显式定义或使用默认 --> </multiInstanceLoopCharacteristics> </userTask>
- 特点: 所有参与者任务实例独立存在、独立完成。流程引擎等待所有实例完成后自动聚合。
2. 或签 (Multi-Instance Parallel - Any One Required
)
- 概念: 一个任务需要多个参与者(通常指人)处理,但只要其中任意一个参与者完成该任务(或达到特定完成条件),流程即可继续向下流转。其他未处理的任务实例会被自动取消。例如:技术支持工单发布到一组工程师,谁先“抢单”处理即可。
- BPMN 实现: 同样使用多实例任务 (
Multi-Instance Task
),并且必须是并行类型 (Parallel
)。 - 关键配置:
- 多实例类型:
Parallel
(必须并行)。 - 实例集合: 指定候选参与者的集合变量 (如
candidateGroupList
)。 - 元素变量: 同上。
- 完成条件:
- 核心:
nrOfCompletedInstances >= 1
(至少一个实例完成)。 - 常用表达式:
${nrOfCompletedInstances > 0}
或${nrOfCompletedInstances >= 1}
。
- 核心:
- 多实例类型:
- XML 片段示例:
<userTask id="claimTask" name="抢单处理"> <multiInstanceLoopCharacteristics isSequential="false" flowable:collection="${supportGroupList}" flowable:elementVariable="candidateGroup"> <completionCondition>${nrOfCompletedInstances >= 1}</completionCondition> </multiInstanceLoopCharacteristics> </userTask>
- 特点: 多个任务实例同时创建。一旦其中一个实例被完成(通常是签收
claim
并完成complete
),引擎立即取消其他所有实例,并继续流程。
3. 分支 (Exclusive Gateway - XOR
)
- 概念: 流程执行到此处,需要根据流程变量的值或条件表达式的结果,从多个可能的后续路径中选择且仅选择一条路径继续执行。这是典型的“决策点”。例如:报销金额
amount < 5000
走经理审批,amount >= 5000
走总监审批。 - BPMN 实现: 使用排他网关 (
Exclusive Gateway
- 菱形图标,内部通常无X
或有时带X
标记)。 - 关键配置:
- 网关出口顺序流: 必须为从网关引出的每一条顺序流 (
Sequence Flow
) 定义条件表达式 (Condition Expression
)。 - 条件表达式: 使用 JUEL/SpEL 等表达式语言,基于流程变量进行判断 (如
${amount < 5000}
,${orderType == 'VIP'}
)。 - 默认流: 可以定义一条默认顺序流 (
Default Flow
),当没有任何其他条件满足时使用。强烈推荐设置默认流以避免流程挂起。
- 网关出口顺序流: 必须为从网关引出的每一条顺序流 (
- XML 片段示例:
<exclusiveGateway id="decisionGateway" name="审批级别决策" /> <sequenceFlow id="toManager" sourceRef="decisionGateway" targetRef="managerApprovalTask"> <conditionExpression xsi:type="tFormalExpression">${amount < 5000}</conditionExpression> </sequenceFlow> <sequenceFlow id="toDirector" sourceRef="decisionGateway" targetRef="directorApprovalTask"> <conditionExpression xsi:type="tFormalExpression">${amount >= 5000}</conditionExpression> </sequenceFlow> <sequenceFlow id="defaultFlow" sourceRef="decisionGateway" targetRef="errorHandlerTask" flowable:isDefault="true" /> <!-- 默认流 -->
- 特点: 互斥选择,只走一条路。条件按顺序流定义的顺序(或在某些引擎实现中按定义顺序)评估,第一个条件为
true
的路径会被执行。
4. 并行 (Parallel Gateway - AND
)
- 概念: 流程执行到此处,会同时触发(分叉)所有后续路径。这些路径上的活动并行执行,互不影响。只有当所有被触发的并行分支都执行完成并汇聚到同一个并行网关时,流程才会继续向下执行(汇聚)。例如:订单处理同时触发“仓库配货”和“财务收款”两个任务,两个任务都完成后才能进行“发货”。
- BPMN 实现: 使用并行网关 (
Parallel Gateway
- 菱形图标,内部通常有+
标记)。- 分叉: 用于将一个执行流拆分成多个并行流。
- 汇聚: 用于将多个并行流合并成一个执行流(等待所有流入分支到达)。
- 关键配置:
- 分叉网关: 网关后的所有顺序流不能有条件表达式!所有流出路径都会被无条件同时触发。
- 汇聚网关: 网关前的所有流入顺序流不需要条件表达式。引擎会在此等待所有从对应分叉网关衍生出来的、尚未完成的执行流到达后,才继续执行汇聚网关后的唯一流出路径。
- 配对: 一个汇聚网关通常对应上游的一个分叉网关。流入汇聚网关的执行流必须是从同一个分叉网关分出去的。
- XML 片段示例 (分叉与汇聚):
<parallelGateway id="forkGateway" name="分叉:并行处理" /> <sequenceFlow id="toWarehouse" sourceRef="forkGateway" targetRef="prepareGoodsTask" /> <!-- 无条件 --> <sequenceFlow id="toFinance" sourceRef="forkGateway" targetRef="receivePaymentTask" /> <!-- 无条件 --> <userTask id="prepareGoodsTask" name="仓库配货" /> <userTask id="receivePaymentTask" name="财务收款" /> <parallelGateway id="joinGateway" name="汇聚:等待完成" /> <sequenceFlow sourceRef="prepareGoodsTask" targetRef="joinGateway" /> <!-- 流入汇聚网关 --> <sequenceFlow sourceRef="receivePaymentTask" targetRef="joinGateway" /> <!-- 流入汇聚网关 --> <sequenceFlow sourceRef="joinGateway" targetRef="shipOrderTask" /> <!-- 流出汇聚网关,无条件 -->
- 特点: 同时启动多条路径,所有路径完成后汇聚继续。路径之间没有顺序依赖,执行速度可能不同。汇聚点是同步点。
核心区别总结
特性 | 会签 (Multi-Instance All) | 或签 (Multi-Instance Any) | 分支 (Exclusive Gateway) | 并行 (Parallel Gateway) |
---|---|---|---|---|
目的 | 所有参与者必须完成同一任务 | 任一参与者完成同一任务 | 选择一条路径执行 | 同时执行多条路径 |
核心元素 | 多实例任务 (User Task) | 多实例任务 (User Task) | 排他网关 (Exclusive Gateway) | 并行网关 (Parallel Gateway) |
实例数量 | 多个任务实例 (每个参与者一个) | 多个任务实例 (每个候选者一个) | 单个执行流 | 多个执行流 (每个分支一个) |
完成条件 | 所有任务实例完成 | 至少一个任务实例完成 | 选中的路径执行完成 | 所有被触发的分支都执行完成 (汇聚点) |
路径关系 | N/A (同一任务的不同实例) | N/A (同一任务的不同实例) | 互斥 (只选一条) | 并发且独立 |
条件配置 | 在任务的多实例配置中 (完成条件) | 在任务的多实例配置中 (完成条件) | 在顺序流上 (条件表达式) | 分叉后顺序流无条件 |
同步点 | 任务本身所有实例完成即同步 | 任务本身任一实例完成即同步 | 无显式同步 (路径内可能异步) | 汇聚网关是显式同步点 |
典型应用 | 全员审批、多方确认 | 抢单、派单、通知任一处理人 | 条件路由、决策点 | 并行处理独立子任务、多线程工作 |
关键注意事项
- 多实例变量:
nrOfInstances
(总实例数),nrOfActiveInstances
(活动实例数),nrOfCompletedInstances
(完成实例数),loopCounter
(当前实例索引) 是多实例任务的内置变量,在完成条件和任务分配中非常有用。 - 集合变量: 会签和或签依赖的集合变量 (
assigneeList
,candidateGroupList
) 必须在流程实例启动前或到达该任务前被正确设置。 - 并行网关汇聚: 务必确保流入汇聚网关的所有分支最终都会到达。如果有分支在运行时因条件永远无法到达汇聚点,流程将永远挂起在汇聚网关!使用超时或边界事件处理潜在死锁。
- 排他网关条件: 条件表达式应覆盖所有预期情况,并设置默认流处理意外值,防止流程挂起。
- 异步延续: 在并行分支或耗时任务中,考虑使用异步延续 (
flowable:async="true"
) 提高吞吐量和响应性。 - 历史记录: 多实例任务会为每个实例生成独立的历史任务记录。并行分支中的每个活动也有独立的历史记录。
理解并熟练运用这四种核心模式,是设计高效、清晰、符合业务逻辑的 Flowable 流程模型的基础。在实际应用中,它们常常组合嵌套使用以构建更复杂的流程场景。