news 2026/6/10 10:14:21

Activiti7 会签多实例任务实战:动态审批人、一票否决与网关路由详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Activiti7 会签多实例任务实战:动态审批人、一票否决与网关路由详解

1. 会签多实例任务的核心概念

会签是工作流中常见的审批场景,多个审批人需要同时对同一事项进行审批。在Activiti7中,这种需求可以通过多实例任务来实现。简单来说,就是把一个任务复制成多份,分发给不同的审批人。

想象一下公司采购申请的审批流程:财务、法务、技术三个部门需要同时审核。传统串行审批需要等前一个部门完成才能到下一个,而会签模式下三个部门可以同时处理,效率提升明显。

Activiti7的多实例任务实现依赖于三个关键属性:

  • collection:审批人集合,比如["财务","法务","技术"]
  • elementVariable:当前处理的审批人变量名
  • completionCondition:任务完成条件

实际项目中我遇到过这样的坑:忘记设置elementVariable导致任务无法分配。正确的做法应该像这样配置:

<multiInstanceLoopCharacteristics activiti:collection="approvers" activiti:elementVariable="approver"> <completionCondition>${nrOfCompletedInstances/nrOfInstances >= 0.6}</completionCondition> </multiInstanceLoopCharacteristics>

2. 动态设置审批人实战

静态配置审批人的方式在实际开发中基本不可行,因为审批人可能来自组织架构、角色配置或特定业务规则。通过RuntimeService传递动态审批人集合才是正确姿势。

最近给客户做OA系统时,我们是这样实现的:先通过组织架构接口获取部门经理列表,再结合业务规则过滤出最终审批人。核心代码如下:

// 获取动态审批人列表 List<String> approvers = orgService.getDepartmentManagers(deptId); // 添加业务规则筛选 approvers = approvers.stream() .filter(u -> !conflictCheckService.hasConflict(u, businessId)) .collect(Collectors.toList()); // 启动流程时传入变量 Map<String, Object> vars = new HashMap<>(); vars.put("approvers", approvers); vars.put("approverCount", approvers.size()); runtimeService.startProcessInstanceByKey("multiApprove", vars);

特别注意:当审批人列表为空时需要特殊处理。我们的做法是添加默认审批人并记录告警日志,避免流程卡死。

3. 一票否决机制的实现

一票否决是会签流程的关键特性。在Activiti中可以通过两种方式实现:

  1. 完成条件表达式
<completionCondition> ${rejected || nrOfCompletedInstances == nrOfInstances} </completionCondition>
  1. 执行监听器动态干预
public class RejectListener implements ExecutionListener { @Override public void notify(DelegateExecution execution) { String comment = (String)execution.getVariable("comment"); if("reject".equals(comment)){ execution.setVariable("rejected", true); // 强制终止其他实例 runtimeService.deleteMultiInstanceExecution( execution.getId(), false); } } }

实测发现第一种方式更简洁,但第二种更灵活。比如我们有个项目需要在否决时自动发送加急通知,就只能用监听器实现。

4. 网关路由的智能判断

会签完成后通常需要根据结果路由到不同分支。排他网关(Exclusive Gateway)配合条件表达式是最佳选择。这里分享几个实用技巧:

条件表达式优化

<conditionExpression xsi:type="tFormalExpression"> <!-- 更健壮的判断逻辑 --> ${!rejected && approvedCount > 0} </conditionExpression>

常见问题排查

  1. 表达式返回null会导致流程挂起
  2. 变量作用域问题(建议使用execution.setVariable)
  3. 类型转换异常(字符串和布尔值比较要特别注意)

在最近的项目中,我们封装了安全的条件表达式工具类:

public class ExpressionUtil { public static boolean safeEval(DelegateExecution exec, String expr) { try { Object result = runtimeService .createConditionEvaluation(exec) .evaluate(expr); return Boolean.TRUE.equals(result); } catch (Exception e) { log.warn("表达式执行失败", e); return false; } } }

5. 完整实现案例解析

结合上述知识点,我们来看一个生产级实现。这个案例包含以下特性:

  • 动态审批人设置
  • 一票否决机制
  • 智能路由判断
  • 审批意见收集

流程定义关键部分

<userTask id="multiApprove" name="会签审批"> <multiInstanceLoopCharacteristics activiti:collection="${approvers}" activiti:elementVariable="currentApprover"> <completionCondition> ${rejected || nrOfCompletedInstances == nrOfInstances} </completionCondition> </multiInstanceLoopCharacteristics> <extensionElements> <activiti:formProperty id="comment" /> <activiti:executionListener event="end" class="com.example.RejectListener"/> </extensionElements> </userTask> <exclusiveGateway id="decisionGateway" /> <sequenceFlow sourceRef="decisionGateway" targetRef="rejectTask"> <conditionExpression>${rejected}</conditionExpression> </sequenceFlow> <sequenceFlow sourceRef="decisionGateway" targetRef="nextStep"> <conditionExpression>${!rejected}</conditionExpression> </sequenceFlow>

监听器实现要点

public class RejectListener implements ExecutionListener { @Override public void notify(DelegateExecution exec) { String comment = (String)exec.getVariable("comment"); if(comment != null && comment.contains("拒绝")){ // 设置否决标志 exec.setVariable("rejected", true); // 记录否决人 String rejecter = (String)exec.getVariable("currentApprover"); exec.setVariable("rejecter", rejecter); // 发送实时通知 notifyService.sendRejectAlert(rejecter); } } }

这个方案在某大型企业的合同审批流程中稳定运行了2年多,日均处理3000+流程实例。关键优化点在于:

  1. 使用异步监听器处理通知逻辑
  2. 添加了完备的日志记录
  3. 对边界条件做了充分处理

6. 性能优化与常见问题

在大规模使用会签任务时,我们踩过不少性能坑。这里分享几个关键优化点:

审批人集合优化

  • 控制审批人数量(建议不超过20人)
  • 使用缓存减少组织架构查询
  • 分批处理超大规模审批

数据库优化

-- 添加必要的索引 CREATE INDEX idx_act_ru_exec_mi ON act_ru_execution(proc_inst_id_, is_mi_root_); -- 定期清理历史数据

常见问题解决方案

  1. 任务卡住:检查nrOfInstances和nrOfActiveInstances是否一致
  2. 网关不触发:确认条件表达式变量已正确设置
  3. 监听器不执行:检查event类型是否匹配(start/end)

在最近一次性能调优中,我们通过以下改动将处理速度提升了5倍:

  • 将同步监听器改为异步
  • 优化变量存储(大对象存MongoDB)
  • 添加流程实例缓存

7. 扩展应用场景

会签模式不仅适用于审批流程,还可以灵活应用于这些场景:

技术评审

  • 代码审查多人并行评审
  • 测试用例多人验证
  • 架构设计多方确认

业务场景

  • 采购多方比价
  • 合同多方签署
  • 项目多方验收

最近我们实现了一个创新的应用:在DevOps流程中使用会签任务控制发布流程。当多个系统需要同时发布时,各系统负责人并行确认准备状态,全部就绪后自动触发发布。关键实现点在于动态设置审批人为各系统负责人,并设置超时自动通过机制。

// 动态设置超时自动通过 timerService.schedule(new Runnable(){ public void run(){ if(!taskService.createTaskQuery() .processInstanceId(procId) .unfinished().list().isEmpty()){ // 自动完成所有任务 tasks.forEach(t -> taskService.complete(t.getId(), autoApproveVars)); } } }, 2, TimeUnit.HOURS);
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/16 16:12:14

EASY-HWID-SPOOFER:内核级硬件信息修改技术实现原理与应用分析

EASY-HWID-SPOOFER&#xff1a;内核级硬件信息修改技术实现原理与应用分析 【免费下载链接】EASY-HWID-SPOOFER 基于内核模式的硬件信息欺骗工具 项目地址: https://gitcode.com/gh_mirrors/ea/EASY-HWID-SPOOFER EASY-HWID-SPOOFER是一款基于Windows内核驱动开发的专业…

作者头像 李华
网站建设 2026/5/16 16:27:47

Claude Code 用户迁移到 Taotoken 以解决账号与额度限制的实践

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 Claude Code 用户迁移到 Taotoken 以解决账号与额度限制的实践 对于深度依赖 Claude Code 这类编程助手的开发者而言&#xff0c;开…

作者头像 李华
网站建设 2026/5/16 16:28:42

PS 套索工具删除多余区域 抠图去杂物详细步骤

用PS套索工具删多余部分总翻车&#xff1f;选不准边缘、删完背景留残痕、复杂素材抠到崩溃&#xff1f;其实只要选对正确方法&#xff0c;不管是不规则图形、棱角物体还是精细边缘&#xff0c;都能高效搞定。今天就来分享3种PS套索工具去掉不要部分的实用方法&#xff0c;干货直…

作者头像 李华
网站建设 2026/5/16 16:25:45

WebToEpub:3步实现网页转EPUB的智能浏览器扩展

WebToEpub&#xff1a;3步实现网页转EPUB的智能浏览器扩展 【免费下载链接】WebToEpub A simple Chrome (and Firefox) Extension that converts Web Novels (and other web pages) into an EPUB. 项目地址: https://gitcode.com/gh_mirrors/we/WebToEpub 还在为网络小说…

作者头像 李华
网站建设 2026/5/16 17:22:55

Go语言实现增强版ARP工具:网络发现与安全审计利器

1. 项目概述&#xff1a;一个被低估的网络“侦察兵” 如果你问我&#xff0c;在网络安全和网络运维的日常工作中&#xff0c;最常用、最基础、但又最容易被忽视的工具是什么&#xff0c;我的答案里一定有 arp 命令。很多人觉得它太“古老”了&#xff0c;不就是查查IP和MAC地…

作者头像 李华
网站建设 2026/5/16 17:21:29

手把手教你用GD32的IPA加速图形显示:从画点画线到UI界面优化

手把手教你用GD32的IPA加速图形显示&#xff1a;从画点画线到UI界面优化 在嵌入式系统开发中&#xff0c;图形界面(GUI)的实现往往面临性能瓶颈。传统基于CPU的图形渲染方式会占用大量处理器资源&#xff0c;导致界面卡顿、响应迟缓。GD32微控制器内置的IPA(Image Processing A…

作者头像 李华