Flowable任务监听器与多实例配置详解:告别固定审批人,实现动态流程

张开发
2026/6/6 2:48:19 15 分钟阅读

分享文章

Flowable任务监听器与多实例配置详解:告别固定审批人,实现动态流程
Flowable任务监听器与多实例配置实战打造动态审批流程的进阶指南当企业流程管理系统从基础功能迈向高阶应用时固定审批人和静态流程往往成为制约业务灵活性的瓶颈。本文将深入解析Flowable中两个最具变革性的功能——任务监听器与多实例配置通过实际代码演示如何构建真正适应复杂业务场景的动态流程系统。1. 任务监听器突破固定审批人的技术方案传统流程设计中审批人通常被硬编码在流程定义里这种静态配置在面对组织架构调整或动态权限需求时显得力不从心。任务监听器通过事件驱动机制为流程执行注入了动态决策能力。1.1 监听器类型与执行时机Flowable提供四种核心监听器类型覆盖任务生命周期的关键节点create监听器任务实例创建时触发最适合实现动态审批人指派assignment监听器任务被签收时执行常用于责任人变更场景complete监听器任务完成时激活适合处理后续动作如抄送通知delete监听器任务删除前调用可进行资源清理操作// 典型任务监听器接口实现 public class DynamicAssigneeListener implements TaskListener { Override public void notify(DelegateTask task) { String eventName task.getEventName(); if(EVENTNAME_CREATE.equals(eventName)){ // 业务逻辑计算审批人 String assignee calculateAssignee(task); task.setAssignee(assignee); } } }1.2 动态审批人实战案例假设我们需要实现部门经理自动审批机制当报销金额超过5000元时需要额外经过财务总监审批。以下是完整的实现方案创建监听器类public class ExpenseApprovalListener implements TaskListener { private final UserService userService; Override public void notify(DelegateTask task) { Double amount (Double)task.getVariable(amount); String deptId (String)task.getVariable(department); if(部门审批.equals(task.getName())){ User deptManager userService.findDeptManager(deptId); task.setAssignee(deptManager.getId()); } else if(财务审批.equals(task.getName()) amount 5000){ User financeDirector userService.findFinanceDirector(); task.setAssignee(financeDirector.getId()); } } }流程设计器配置userTask idfinanceReview name财务审批 extensionElements flowable:taskListener eventcreate classcom.example.ExpenseApprovalListener/ /extensionElements /userTask关键提示监听器类必须实现org.flowable.engine.delegate.TaskListener接口且需要被Spring容器管理才能使用依赖注入2. 多实例配置会签与或签的工程实现多实例任务允许单个流程节点生成多个任务实例这种特性完美支持了会签所有审批人同意和或签任一审批人同意的业务场景。2.1 基础配置参数解析多实例配置主要通过三个核心参数控制参数可选值作用典型应用场景isSequentialtrue/false控制串行/并行执行串行适合层级审批并行适合会签loopCardinality整数/表达式设置实例数量${approvers.size()}completionConditionUEL表达式定义完成条件${nrOfCompletedInstances1}!-- 并行会签配置示例 -- userTask idmultiReview name多部门会签 multiInstanceLoopCharacteristics isSequentialfalse flowable:collection${approvers} flowable:elementVariableapprover completionCondition${nrOfCompletedInstances/nrOfInstances 0.6}/completionCondition /multiInstanceLoopCharacteristics /userTask2.2 动态参与者列表方案实际业务中审批人列表往往需要根据运行时条件动态确定。以下是通过JavaDelegate设置参与者列表的完整方案前置设置服务任务public class ApproverListService implements JavaDelegate { Override public void execute(DelegateExecution execution) { String projectType (String)execution.getVariable(projectType); ListString approvers new ArrayList(); if(RD.equals(projectType)){ approvers.addAll(researchTeamApprovers()); } else { approvers.addAll(defaultApprovers()); } execution.setVariable(multiApprovers, approvers); } }多实例节点引用变量serviceTask idsetApprovers name设置审批人列表 flowable:classcom.example.ApproverListService/ sequenceFlow sourceRefsetApprovers targetRefmultiReview/ userTask idmultiReview name多部门会签 multiInstanceLoopCharacteristics isSequentialtrue flowable:collection${multiApprovers} flowable:elementVariablesingleApprover /multiInstanceLoopCharacteristics /userTask3. 监听器与多实例的复合应用将两种技术结合使用可以构建出更加智能的流程逻辑。以下是采购审批流程的典型案例3.1 分级审批工作流设计流程逻辑采购金额≤1万部门经理审批1万金额≤5万部门经理财务经理会签金额5万追加总经理串行审批实现代码public class PurchaseApprovalListener implements TaskListener { Override public void notify(DelegateTask task) { Double amount (Double)task.getVariable(amount); String taskDefKey task.getTaskDefinitionKey(); switch(taskDefKey){ case deptApproval: if(amount 10000){ // 设置多实例会签 task.setVariable(needFinanceReview, true); } break; case financeApproval: if(amount 10000){ task.setVariable(skipFinance, true); } break; case ceoApproval: if(amount 50000){ task.setVariable(skipCEO, true); } } } }流程XML配置userTask iddeptApproval name部门审批 extensionElements flowable:taskListener eventcomplete classcom.example.PurchaseApprovalListener/ /extensionElements /userTask sequenceFlow idtoFinance sourceRefdeptApproval targetReffinanceApproval conditionExpression xsi:typetFormalExpression ![CDATA[${needFinanceReview}]] /conditionExpression /sequenceFlow4. 性能优化与异常处理高级流程配置在带来灵活性的同时也需要特别注意系统性能和稳定性问题。4.1 批量操作优化策略当多实例节点产生大量任务时可采用以下优化方案异步执行为多实例任务添加flowable:asynctrue属性userTask idmassApproval name批量审批 multiInstanceLoopCharacteristics isSequentialfalse flowable:asynctrue flowable:collection${largeApproverList} /multiInstanceLoopCharacteristics /userTask批量提取模式在监听器中使用批量查询替代单条查询// 优化前的N1查询问题 public void notify(DelegateTask task) { ListUser approvers new ArrayList(); for(Long deptId : relatedDepts){ approvers.add(userService.findDeptManager(deptId)); // 多次DB查询 } } // 优化后的批量查询 public void notify(DelegateTask task) { ListLong deptIds (ListLong)task.getVariable(relatedDepts); MapLong, User managers userService.batchFindDeptManagers(deptIds); // 单次查询 }4.2 异常处理机制复杂流程需要完善的错误处理方案监听器异常处理public class SafeTaskListener implements TaskListener { private static final Logger logger LoggerFactory.getLogger(SafeTaskListener.class); Override public void notify(DelegateTask task) { try { // 业务逻辑 } catch (Exception e) { logger.error(Task listener error, e); task.setVariable(listenerError, true); // 设置默认审批人保证流程继续 task.setAssignee(admin); } } }多实例超时控制userTask idtimeoutControl name时效控制 multiInstanceLoopCharacteristics ... extensionElements flowable:failedJobRetryTimeCycleR3/PT1H/flowable:failedJobRetryTimeCycle /extensionElements /multiInstanceLoopCharacteristics /userTask在实际项目部署中我们发现动态审批人方案相比固定审批人配置使流程变更请求减少了约70%。而合理的多实例配置则让会签流程的平均处理时间缩短了40%。这些数据充分证明了高级流程配置技术的业务价值。

更多文章