在业务流程管理(BPM)领域,合理选择和应用流程模式对于满足复杂业务需求至关重要。Flowable作为一个灵活的BPM引擎,支持多种流程控制模式的实现。本文将重点介绍四种常用的流程模式:会签流程、或签流程、分支流程和并行流程,并结合Flowable展示其具体实现方法。 在深入了解各种流程模式之前,先简单介绍一下BPMN基本概念: 会签流程(也称为"全部审批"模式)要求多个参与者必须全部同意才能继续流程。这常用于重要决策审批、合同审核等场景。 在Flowable中,会签流程主要通过多实例用户任务(Multi-Instance User Task)实现,配合条件表达式控制流程走向。 上面的示例中: 在实际应用中,会签流程常常需要处理一些特殊情况: 动态会签人:根据业务数据动态确定审批人 会签结果汇总:收集所有审批人的意见 或签流程(也称为"任一审批"模式)只需要多个参与者中的任意一个同意即可继续流程。这适用于一般性审批、资源分配等场景。 或签流程在Flowable中同样使用多实例用户任务实现,但通过完成条件(completionCondition)控制只需一人完成即可。 上面的示例中: 除了多实例方式外,也可以使用候选人(Candidate)机制实现或签: 配合Java代码: 分支流程(也称为"条件路由"模式)根据业务条件选择不同的执行路径。这是BPM中最常用的控制流模式之一。 在Flowable中,分支流程主要通过排他网关(Exclusive Gateway)实现: 当需要同时选择多个满足条件的分支时,可以使用包容网关(Inclusive Gateway): 在实际应用中,我们可以通过Java代码动态设置流程变量,进而控制分支流向: 并行流程(也称为"同步执行"模式)允许多个活动同时执行,提高流程效率。适用于相互独立的任务处理场景。 在Flowable中,并行流程通过并行网关(Parallel Gateway)实现: 并行流和会签可以结合使用,实现更复杂的业务场景: 下面是一个结合了上述四种流程模式的采购审批流程示例: 使用Java代码启动上述流程: 在使用Flowable设计和实现上述流程模式时,以下是一些最佳实践建议: 明确业务需求:在选择流程模式前,明确业务需要"会签"还是"或签",是否有分支条件等。 简化流程设计:流程设计应尽量简洁,避免过度复杂的路由逻辑。 合理使用表达式:流程条件表达式应清晰、简单,易于维护。 考虑异常处理:设计流程时,需考虑异常情况,如审批人不在岗、驳回处理等。 预留扩展点:流程设计应考虑未来可能的变更,预留扩展点。 使用监听器记录关键事件: BPM流程设计中的会签流程、或签流程、分支流程和并行流程是解决复杂业务场景的基础模式。Flowable通过其灵活的BPMN实现和丰富的API,提供了这些模式的完整支持。通过合理组合这些模式,可以构建出满足各种业务需求的复杂工作流,提高业务流程的自动化水平和执行效率。 在实际应用中,应根据具体业务场景选择适当的流程模式,并遵循流程设计的最佳实践,确保流程定义清晰、高效且可维护。Flowable作为一个成熟的BPM引擎,为这些流程模式的落地实施提供了强大的技术支持。流程模式基础概念
会签流程模式
会签流程的特点
Flowable中的会签实现
<userTask id="approvalTask" name="部门经理审批" flowable:assignee="${assignee}">
<multiInstanceLoopCharacteristics isSequential="false">
<loopCardinality>${nrOfApprovers}</loopCardinality>
<completionCondition>${nrOfCompletedInstances == nrOfInstances}</completionCondition>
</multiInstanceLoopCharacteristics>
</userTask>
isSequential="false" 表示所有审批任务会并行创建completionCondition 设置为只有当所有实例都完成时才继续流程会签流程的核心API使用
// 设置审批人列表
List<String> approverList = Arrays.asList("manager1", "manager2", "manager3");
Map<String, Object> variables = new HashMap<>();
variables.put("approverList", approverList);
variables.put("nrOfApprovers", approverList.size());
// 启动会签流程
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(
"contractApprovalProcess",
"CONTRACT-2025-001",
variables
);
// 查询当前待办任务
List<Task> tasks = taskService.createTaskQuery()
.processInstanceId(processInstance.getId())
.taskCandidateOrAssigned("manager1")
.list();
会签流程的高级应用
// 动态构建审批人列表
List<String> approvers = userService.getDepartmentManagers(departmentId);
execution.setVariable("approverList", approvers);
execution.setVariable("nrOfApprovers", approvers.size());
<multiInstanceLoopCharacteristics isSequential="false">
<loopCardinality>${nrOfApprovers}</loopCardinality>
<inputDataItem name="approver" />
<inputDataItem name="comments" />
<completionCondition>${nrOfCompletedInstances == nrOfInstances}</completionCondition>
</multiInstanceLoopCharacteristics>
或签流程模式
或签流程的特点
Flowable中的或签实现
<userTask id="approvalTask" name="部门审批" flowable:assignee="${assignee}">
<multiInstanceLoopCharacteristics isSequential="false">
<loopCardinality>${nrOfApprovers}</loopCardinality>
<completionCondition>${nrOfCompletedInstances >= 1}</completionCondition>
</multiInstanceLoopCharacteristics>
</userTask>
completionCondition 设置为只要有一个实例完成即可继续流程候选人方式实现或签
<userTask id="approvalTask" name="部门审批">
<potentialOwner>
<resourceAssignmentExpression>
<formalExpression>user1,user2,user3</formalExpression>
</resourceAssignmentExpression>
</potentialOwner>
</userTask>
// 设置候选人
List<String> candidateUsers = Arrays.asList("user1", "user2", "user3");
for (String user : candidateUsers) {
taskService.addCandidateUser(task.getId(), user);
}
// 认领任务
taskService.claim(taskId, "user1");
// 完成任务
taskService.complete(taskId);
分支流程模式
分支流程的特点
排他网关实现分支
<exclusiveGateway id="approvalDecision" name="审批决策" />
<sequenceFlow id="flow1" sourceRef="approvalDecision" targetRef="approvedPath">
<conditionExpression xsi:type="tFormalExpression">${approved == true}</conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow2" sourceRef="approvalDecision" targetRef="rejectedPath">
<conditionExpression xsi:type="tFormalExpression">${approved == false}</conditionExpression>
</sequenceFlow>
包容网关实现复杂分支
<inclusiveGateway id="riskAssessment" name="风险评估" />
<sequenceFlow id="flow1" sourceRef="riskAssessment" targetRef="creditCheck">
<conditionExpression xsi:type="tFormalExpression">${amount > 10000}</conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow2" sourceRef="riskAssessment" targetRef="identityVerification">
<conditionExpression xsi:type="tFormalExpression">${customerType == 'new'}</conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow3" sourceRef="riskAssessment" targetRef="basicProcessing">
<conditionExpression xsi:type="tFormalExpression">${amount <= 10000 && customerType != 'new'}</conditionExpression>
</sequenceFlow>
动态分支控制
// 设置决策变量
Map<String, Object> variables = new HashMap<>();
variables.put("approved", riskScore > 70);
variables.put("amount", loanRequest.getAmount());
variables.put("customerType", customer.getType());
// 完成任务,触发网关决策
taskService.complete(taskId, variables);
并行流程模式
并行流程的特点
并行网关实现
<!-- 分叉:开始并行执行 -->
<parallelGateway id="forkProcess" />
<sequenceFlow id="flow1" sourceRef="startEvent" targetRef="forkProcess" />
<sequenceFlow id="flow2" sourceRef="forkProcess" targetRef="documentReview" />
<sequenceFlow id="flow3" sourceRef="forkProcess" targetRef="technicalReview" />
<sequenceFlow id="flow4" sourceRef="forkProcess" targetRef="financialReview" />
<!-- 各并行任务 -->
<userTask id="documentReview" name="文档审查" />
<userTask id="technicalReview" name="技术评估" />
<userTask id="financialReview" name="财务审核" />
<!-- 汇合:等待所有并行分支完成 -->
<sequenceFlow id="flow5" sourceRef="documentReview" targetRef="joinProcess" />
<sequenceFlow id="flow6" sourceRef="technicalReview" targetRef="joinProcess" />
<sequenceFlow id="flow7" sourceRef="financialReview" targetRef="joinProcess" />
<parallelGateway id="joinProcess" />
<sequenceFlow id="flow8" sourceRef="joinProcess" targetRef="finalApproval" />
并行流与会签结合
<parallelGateway id="forkProcess" />
<sequenceFlow id="flow1" sourceRef="forkProcess" targetRef="hrApproval" />
<sequenceFlow id="flow2" sourceRef="forkProcess" targetRef="financeApproval" />
<!-- HR部门会签 -->
<userTask id="hrApproval" name="HR部门审批" flowable:assignee="${hrApprover}">
<multiInstanceLoopCharacteristics isSequential="false">
<loopCardinality>${hrApproverCount}</loopCardinality>
<completionCondition>${nrOfCompletedInstances == nrOfInstances}</completionCondition>
</multiInstanceLoopCharacteristics>
</userTask>
<!-- 财务部门会签 -->
<userTask id="financeApproval" name="财务部门审批" flowable:assignee="${financeApprover}">
<multiInstanceLoopCharacteristics isSequential="false">
<loopCardinality>${financeApproverCount}</loopCardinality>
<completionCondition>${nrOfCompletedInstances == nrOfInstances}</completionCondition>
</multiInstanceLoopCharacteristics>
</userTask>
<parallelGateway id="joinProcess" />
实际应用场景:采购审批流程
<process id="purchaseApprovalProcess" name="采购审批流程">
<startEvent id="startEvent" />
<sequenceFlow id="flow1" sourceRef="startEvent" targetRef="initiatePurchase" />
<!-- 初始化采购申请 -->
<userTask id="initiatePurchase" name="填写采购申请" />
<sequenceFlow id="flow2" sourceRef="initiatePurchase" targetRef="amountGateway" />
<!-- 分支流:根据金额决定审批路径 -->
<exclusiveGateway id="amountGateway" />
<sequenceFlow id="flow3" sourceRef="amountGateway" targetRef="simpleApproval">
<conditionExpression xsi:type="tFormalExpression">${amount <= 10000}</conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow4" sourceRef="amountGateway" targetRef="complexApprovalFork">
<conditionExpression xsi:type="tFormalExpression">${amount > 10000}</conditionExpression>
</sequenceFlow>
<!-- 或签流程:小额采购任一经理审批 -->
<userTask id="simpleApproval" name="经理审批">
<potentialOwner>
<resourceAssignmentExpression>
<formalExpression>manager1,manager2,manager3</formalExpression>
</resourceAssignmentExpression>
</potentialOwner>
</userTask>
<sequenceFlow id="flow5" sourceRef="simpleApproval" targetRef="endEvent" />
<!-- 并行流程:大额采购需多部门审核 -->
<parallelGateway id="complexApprovalFork" />
<sequenceFlow id="flow6" sourceRef="complexApprovalFork" targetRef="departmentApproval" />
<sequenceFlow id="flow7" sourceRef="complexApprovalFork" targetRef="financeCheck" />
<!-- 会签流程:部门经理全部审批 -->
<userTask id="departmentApproval" name="部门经理审批" flowable:assignee="${assignee}">
<multiInstanceLoopCharacteristics isSequential="false">
<loopCardinality>${nrOfManagers}</loopCardinality>
<completionCondition>${nrOfCompletedInstances == nrOfInstances}</completionCondition>
</multiInstanceLoopCharacteristics>
</userTask>
<!-- 财务审核 -->
<userTask id="financeCheck" name="财务审核" />
<!-- 汇合所有审批 -->
<sequenceFlow id="flow8" sourceRef="departmentApproval" targetRef="complexApprovalJoin" />
<sequenceFlow id="flow9" sourceRef="financeCheck" targetRef="complexApprovalJoin" />
<parallelGateway id="complexApprovalJoin" />
<!-- 最终CEO审批 -->
<sequenceFlow id="flow10" sourceRef="complexApprovalJoin" targetRef="ceoApproval" />
<userTask id="ceoApproval" name="CEO审批" />
<sequenceFlow id="flow11" sourceRef="ceoApproval" targetRef="endEvent" />
<endEvent id="endEvent" />
</process>
// 设置流程变量
Map<String, Object> variables = new HashMap<>();
variables.put("amount", 15000);
variables.put("nrOfManagers", 3);
variables.put("assignee1", "manager1");
variables.put("assignee2", "manager2");
variables.put("assignee3", "manager3");
// 启动流程实例
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(
"purchaseApprovalProcess",
"PUR-2025-001",
variables
);
流程模式设计最佳实践
public class ApprovalTaskListener implements TaskListener {
@Override
public void notify(DelegateTask delegateTask) {
if (TaskListener.EVENTNAME_COMPLETE.equals(delegateTask.getEventName())) {
// 记录任务完成事件
boolean approved = (boolean) delegateTask.getVariable("approved");
String comment = (String) delegateTask.getVariable("comment");
LoggingService.logApproval(delegateTask.getId(), approved, comment);
}
}
}
总结
在业务流程管理(BPM)领域,合理选择和应用流程模式对于满足复杂业务需求至关重要。Flowable作为一个灵活的BPM引擎,支持多种流程控制模式的实现。本文将重点介绍四种常用的流程模式:会签流程、或签流程、分支流程和并行流程,并结合Flowable展示其具体实现方法。 在深入了解各种流程模式之前,先简单介绍一下BPMN基本概念: 会签流程(也称为"全部审批"模式)要求多个参与者必须全部同意才能继续流程。这常用于重要决策审批、合同审核等场景。 在Flowable中,会签流程主要通过多实例用户任务(Multi-Instance User Task)实现,配合条件表达式控制流程走向。 上面的示例中: 在实际应用中,会签流程常常需要处理一些特殊情况: 动态会签人:根据业务数据动态确定审批人 会签结果汇总:收集所有审批人的意见 或签流程(也称为"任一审批"模式)只需要多个参与者中的任意一个同意即可继续流程。这适用于一般性审批、资源分配等场景。 或签流程在Flowable中同样使用多实例用户任务实现,但通过完成条件(completionCondition)控制只需一人完成即可。 上面的示例中: 除了多实例方式外,也可以使用候选人(Candidate)机制实现或签: 配合Java代码: 分支流程(也称为"条件路由"模式)根据业务条件选择不同的执行路径。这是BPM中最常用的控制流模式之一。 在Flowable中,分支流程主要通过排他网关(Exclusive Gateway)实现: 当需要同时选择多个满足条件的分支时,可以使用包容网关(Inclusive Gateway): 在实际应用中,我们可以通过Java代码动态设置流程变量,进而控制分支流向: 并行流程(也称为"同步执行"模式)允许多个活动同时执行,提高流程效率。适用于相互独立的任务处理场景。 在Flowable中,并行流程通过并行网关(Parallel Gateway)实现: 并行流和会签可以结合使用,实现更复杂的业务场景: 下面是一个结合了上述四种流程模式的采购审批流程示例: 使用Java代码启动上述流程: 在使用Flowable设计和实现上述流程模式时,以下是一些最佳实践建议: 明确业务需求:在选择流程模式前,明确业务需要"会签"还是"或签",是否有分支条件等。 简化流程设计:流程设计应尽量简洁,避免过度复杂的路由逻辑。 合理使用表达式:流程条件表达式应清晰、简单,易于维护。 考虑异常处理:设计流程时,需考虑异常情况,如审批人不在岗、驳回处理等。 预留扩展点:流程设计应考虑未来可能的变更,预留扩展点。 使用监听器记录关键事件: BPM流程设计中的会签流程、或签流程、分支流程和并行流程是解决复杂业务场景的基础模式。Flowable通过其灵活的BPMN实现和丰富的API,提供了这些模式的完整支持。通过合理组合这些模式,可以构建出满足各种业务需求的复杂工作流,提高业务流程的自动化水平和执行效率。 在实际应用中,应根据具体业务场景选择适当的流程模式,并遵循流程设计的最佳实践,确保流程定义清晰、高效且可维护。Flowable作为一个成熟的BPM引擎,为这些流程模式的落地实施提供了强大的技术支持。流程模式基础概念
会签流程模式
会签流程的特点
Flowable中的会签实现
<userTask id="approvalTask" name="部门经理审批" flowable:assignee="${assignee}">
<multiInstanceLoopCharacteristics isSequential="false">
<loopCardinality>${nrOfApprovers}</loopCardinality>
<completionCondition>${nrOfCompletedInstances == nrOfInstances}</completionCondition>
</multiInstanceLoopCharacteristics>
</userTask>
isSequential="false" 表示所有审批任务会并行创建completionCondition 设置为只有当所有实例都完成时才继续流程会签流程的核心API使用
// 设置审批人列表
List<String> approverList = Arrays.asList("manager1", "manager2", "manager3");
Map<String, Object> variables = new HashMap<>();
variables.put("approverList", approverList);
variables.put("nrOfApprovers", approverList.size());
// 启动会签流程
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(
"contractApprovalProcess",
"CONTRACT-2025-001",
variables
);
// 查询当前待办任务
List<Task> tasks = taskService.createTaskQuery()
.processInstanceId(processInstance.getId())
.taskCandidateOrAssigned("manager1")
.list();
会签流程的高级应用
// 动态构建审批人列表
List<String> approvers = userService.getDepartmentManagers(departmentId);
execution.setVariable("approverList", approvers);
execution.setVariable("nrOfApprovers", approvers.size());
<multiInstanceLoopCharacteristics isSequential="false">
<loopCardinality>${nrOfApprovers}</loopCardinality>
<inputDataItem name="approver" />
<inputDataItem name="comments" />
<completionCondition>${nrOfCompletedInstances == nrOfInstances}</completionCondition>
</multiInstanceLoopCharacteristics>
或签流程模式
或签流程的特点
Flowable中的或签实现
<userTask id="approvalTask" name="部门审批" flowable:assignee="${assignee}">
<multiInstanceLoopCharacteristics isSequential="false">
<loopCardinality>${nrOfApprovers}</loopCardinality>
<completionCondition>${nrOfCompletedInstances >= 1}</completionCondition>
</multiInstanceLoopCharacteristics>
</userTask>
completionCondition 设置为只要有一个实例完成即可继续流程候选人方式实现或签
<userTask id="approvalTask" name="部门审批">
<potentialOwner>
<resourceAssignmentExpression>
<formalExpression>user1,user2,user3</formalExpression>
</resourceAssignmentExpression>
</potentialOwner>
</userTask>
// 设置候选人
List<String> candidateUsers = Arrays.asList("user1", "user2", "user3");
for (String user : candidateUsers) {
taskService.addCandidateUser(task.getId(), user);
}
// 认领任务
taskService.claim(taskId, "user1");
// 完成任务
taskService.complete(taskId);
分支流程模式
分支流程的特点
排他网关实现分支
<exclusiveGateway id="approvalDecision" name="审批决策" />
<sequenceFlow id="flow1" sourceRef="approvalDecision" targetRef="approvedPath">
<conditionExpression xsi:type="tFormalExpression">${approved == true}</conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow2" sourceRef="approvalDecision" targetRef="rejectedPath">
<conditionExpression xsi:type="tFormalExpression">${approved == false}</conditionExpression>
</sequenceFlow>
包容网关实现复杂分支
<inclusiveGateway id="riskAssessment" name="风险评估" />
<sequenceFlow id="flow1" sourceRef="riskAssessment" targetRef="creditCheck">
<conditionExpression xsi:type="tFormalExpression">${amount > 10000}</conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow2" sourceRef="riskAssessment" targetRef="identityVerification">
<conditionExpression xsi:type="tFormalExpression">${customerType == 'new'}</conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow3" sourceRef="riskAssessment" targetRef="basicProcessing">
<conditionExpression xsi:type="tFormalExpression">${amount <= 10000 && customerType != 'new'}</conditionExpression>
</sequenceFlow>
动态分支控制
// 设置决策变量
Map<String, Object> variables = new HashMap<>();
variables.put("approved", riskScore > 70);
variables.put("amount", loanRequest.getAmount());
variables.put("customerType", customer.getType());
// 完成任务,触发网关决策
taskService.complete(taskId, variables);
并行流程模式
并行流程的特点
并行网关实现
<!-- 分叉:开始并行执行 -->
<parallelGateway id="forkProcess" />
<sequenceFlow id="flow1" sourceRef="startEvent" targetRef="forkProcess" />
<sequenceFlow id="flow2" sourceRef="forkProcess" targetRef="documentReview" />
<sequenceFlow id="flow3" sourceRef="forkProcess" targetRef="technicalReview" />
<sequenceFlow id="flow4" sourceRef="forkProcess" targetRef="financialReview" />
<!-- 各并行任务 -->
<userTask id="documentReview" name="文档审查" />
<userTask id="technicalReview" name="技术评估" />
<userTask id="financialReview" name="财务审核" />
<!-- 汇合:等待所有并行分支完成 -->
<sequenceFlow id="flow5" sourceRef="documentReview" targetRef="joinProcess" />
<sequenceFlow id="flow6" sourceRef="technicalReview" targetRef="joinProcess" />
<sequenceFlow id="flow7" sourceRef="financialReview" targetRef="joinProcess" />
<parallelGateway id="joinProcess" />
<sequenceFlow id="flow8" sourceRef="joinProcess" targetRef="finalApproval" />
并行流与会签结合
<parallelGateway id="forkProcess" />
<sequenceFlow id="flow1" sourceRef="forkProcess" targetRef="hrApproval" />
<sequenceFlow id="flow2" sourceRef="forkProcess" targetRef="financeApproval" />
<!-- HR部门会签 -->
<userTask id="hrApproval" name="HR部门审批" flowable:assignee="${hrApprover}">
<multiInstanceLoopCharacteristics isSequential="false">
<loopCardinality>${hrApproverCount}</loopCardinality>
<completionCondition>${nrOfCompletedInstances == nrOfInstances}</completionCondition>
</multiInstanceLoopCharacteristics>
</userTask>
<!-- 财务部门会签 -->
<userTask id="financeApproval" name="财务部门审批" flowable:assignee="${financeApprover}">
<multiInstanceLoopCharacteristics isSequential="false">
<loopCardinality>${financeApproverCount}</loopCardinality>
<completionCondition>${nrOfCompletedInstances == nrOfInstances}</completionCondition>
</multiInstanceLoopCharacteristics>
</userTask>
<parallelGateway id="joinProcess" />
实际应用场景:采购审批流程
<process id="purchaseApprovalProcess" name="采购审批流程">
<startEvent id="startEvent" />
<sequenceFlow id="flow1" sourceRef="startEvent" targetRef="initiatePurchase" />
<!-- 初始化采购申请 -->
<userTask id="initiatePurchase" name="填写采购申请" />
<sequenceFlow id="flow2" sourceRef="initiatePurchase" targetRef="amountGateway" />
<!-- 分支流:根据金额决定审批路径 -->
<exclusiveGateway id="amountGateway" />
<sequenceFlow id="flow3" sourceRef="amountGateway" targetRef="simpleApproval">
<conditionExpression xsi:type="tFormalExpression">${amount <= 10000}</conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow4" sourceRef="amountGateway" targetRef="complexApprovalFork">
<conditionExpression xsi:type="tFormalExpression">${amount > 10000}</conditionExpression>
</sequenceFlow>
<!-- 或签流程:小额采购任一经理审批 -->
<userTask id="simpleApproval" name="经理审批">
<potentialOwner>
<resourceAssignmentExpression>
<formalExpression>manager1,manager2,manager3</formalExpression>
</resourceAssignmentExpression>
</potentialOwner>
</userTask>
<sequenceFlow id="flow5" sourceRef="simpleApproval" targetRef="endEvent" />
<!-- 并行流程:大额采购需多部门审核 -->
<parallelGateway id="complexApprovalFork" />
<sequenceFlow id="flow6" sourceRef="complexApprovalFork" targetRef="departmentApproval" />
<sequenceFlow id="flow7" sourceRef="complexApprovalFork" targetRef="financeCheck" />
<!-- 会签流程:部门经理全部审批 -->
<userTask id="departmentApproval" name="部门经理审批" flowable:assignee="${assignee}">
<multiInstanceLoopCharacteristics isSequential="false">
<loopCardinality>${nrOfManagers}</loopCardinality>
<completionCondition>${nrOfCompletedInstances == nrOfInstances}</completionCondition>
</multiInstanceLoopCharacteristics>
</userTask>
<!-- 财务审核 -->
<userTask id="financeCheck" name="财务审核" />
<!-- 汇合所有审批 -->
<sequenceFlow id="flow8" sourceRef="departmentApproval" targetRef="complexApprovalJoin" />
<sequenceFlow id="flow9" sourceRef="financeCheck" targetRef="complexApprovalJoin" />
<parallelGateway id="complexApprovalJoin" />
<!-- 最终CEO审批 -->
<sequenceFlow id="flow10" sourceRef="complexApprovalJoin" targetRef="ceoApproval" />
<userTask id="ceoApproval" name="CEO审批" />
<sequenceFlow id="flow11" sourceRef="ceoApproval" targetRef="endEvent" />
<endEvent id="endEvent" />
</process>
// 设置流程变量
Map<String, Object> variables = new HashMap<>();
variables.put("amount", 15000);
variables.put("nrOfManagers", 3);
variables.put("assignee1", "manager1");
variables.put("assignee2", "manager2");
variables.put("assignee3", "manager3");
// 启动流程实例
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(
"purchaseApprovalProcess",
"PUR-2025-001",
variables
);
流程模式设计最佳实践
public class ApprovalTaskListener implements TaskListener {
@Override
public void notify(DelegateTask delegateTask) {
if (TaskListener.EVENTNAME_COMPLETE.equals(delegateTask.getEventName())) {
// 记录任务完成事件
boolean approved = (boolean) delegateTask.getVariable("approved");
String comment = (String) delegateTask.getVariable("comment");
LoggingService.logApproval(delegateTask.getId(), approved, comment);
}
}
}
总结