当前位置: 首页 > news >正文

别再傻傻分不清了!Camunda 7 多实例任务(会签)的三种审批规则,我用一个请假流程给你讲明白

Camunda 7多实例任务审批规则实战:从请假流程看会签、或签与比例签

想象一下这样的场景:公司市场部的小张需要申请一周的年假,按照公司规定,这个请假申请需要经过部门经理、HR主管和分管副总的三重审批。但问题来了——这三位领导是必须全部同意才能通过?还是只要其中任意一人同意即可?又或者需要超过半数同意?这些不同的审批规则,正是Camunda工作流引擎中多实例任务(Multi-Instance Task)的典型应用场景。

对于刚接触Camunda的开发者来说,理解"会签"、"或签"和"比例签"这些概念可能有些抽象。本文将通过一个完整的请假审批流程示例,带你深入理解这三种审批规则的实际应用。我们将从业务需求出发,反向推导技术配置,重点分析不同规则下Assignee、Collection和Completion Condition的关键差异,并提供可直接运行的流程定义XML和Java测试代码。

1. 业务场景分析与技术映射

在开始编码之前,我们需要先明确业务需求与技术实现的对应关系。以请假流程为例,常见的审批规则有三种:

  1. 会签(全体通过):所有审批人必须全部同意,请假申请才能通过。适用于重要决策场景,如高管休假或长期病假审批。

  2. 或签(一人通过):任意一位审批人同意即可通过。适用于紧急情况或简单事务审批,如短时请假。

  3. 比例签(多数通过):达到特定比例的审批人同意即可通过(如超过50%)。适用于需要民主决策但又不必全体同意的场景。

在Camunda中,这三种规则都通过多实例用户任务(Multi-Instance User Task)实现,核心区别在于完成条件(Completion Condition)的配置。以下是技术实现的关键要素对照表:

要素会签或签比例签
完成条件表达式${nrOfCompletedInstances == nrOfInstances}${nrOfCompletedInstances >= 1}${nrOfCompletedInstances/nrOfInstances > 0.5}
业务语义必须全部同意任意一人同意即可超过半数同意
适用场景高风险决策低风险常规审批中等重要性决策

2. 流程定义设计与XML配置

让我们构建一个包含三种审批规则的完整请假流程。流程包含四个主要节点:

  1. 请假申请提交(发起人节点)
  2. 或签审批节点(一人通过即可)
  3. 比例签审批节点(超过30%通过)
  4. 会签审批节点(全部通过)

对应的BPMN XML配置如下:

<bpmn:process id="leave_approval" isExecutable="true"> <!-- 发起人节点 --> <bpmn:userTask id="submit_leave" name="提交请假申请" camunda:assignee="${initiator}"> <bpmn:incoming>StartEvent_1</bpmn:incoming> <bpmn:outgoing>SequenceFlow_1</bpmn:outgoing> </bpmn:userTask> <!-- 或签审批节点 --> <bpmn:userTask id="or_approval" name="或签审批" camunda:assignee="${approver}"> <bpmn:multiInstanceLoopCharacteristics camunda:collection="${orApprovers}" camunda:elementVariable="approver"> <bpmn:completionCondition> ${nrOfCompletedInstances >= 1} </bpmn:completionCondition> </bpmn:multiInstanceLoopCharacteristics> </bpmn:userTask> <!-- 比例签审批节点 --> <bpmn:userTask id="ratio_approval" name="比例签审批" camunda:assignee="${approver}"> <bpmn:multiInstanceLoopCharacteristics camunda:collection="${ratioApprovers}" camunda:elementVariable="approver"> <bpmn:completionCondition> ${nrOfCompletedInstances/nrOfInstances > 0.3} </bpmn:completionCondition> </bpmn:multiInstanceLoopCharacteristics> </bpmn:userTask> <!-- 会签审批节点 --> <bpmn:userTask id="all_approval" name="会签审批" camunda:assignee="${approver}"> <bpmn:multiInstanceLoopCharacteristics camunda:collection="${allApprovers}" camunda:elementVariable="approver"> <bpmn:completionCondition> ${nrOfCompletedInstances == nrOfInstances} </bpmn:completionCondition> </bpmn:multiInstanceLoopCharacteristics> </bpmn:userTask> </bpmn:process>

关键配置说明:

  • camunda:collection:指定审批人列表变量
  • camunda:elementVariable:定义当前审批人变量
  • completionCondition:使用表达式定义完成条件

3. Java实现与测试案例

下面我们通过Java代码部署流程定义并测试不同审批场景:

@RestController @RequestMapping("/leave") public class LeaveApprovalController { @Autowired private RuntimeService runtimeService; @Autowired private TaskService taskService; // 启动请假流程 @PostMapping("/start") public String startProcess(@RequestBody LeaveRequest request) { Map<String, Object> variables = new HashMap<>(); // 设置审批人列表 variables.put("orApprovers", Arrays.asList("manager1", "manager2")); variables.put("ratioApprovers", Arrays.asList("hr1", "hr2", "hr3")); variables.put("allApprovers", Arrays.asList("vp1", "vp2", "vp3")); variables.put("initiator", request.getApplicantId()); ProcessInstance instance = runtimeService.startProcessInstanceByKey( "leave_approval", request.getBusinessKey(), variables ); return instance.getId(); } // 完成任务审批 @PostMapping("/complete") public void completeTask(@RequestBody ApprovalRequest request) { Map<String, Object> taskVariables = new HashMap<>(); taskVariables.put("approved", request.isApproved()); taskService.complete(request.getTaskId(), taskVariables); } }

测试不同审批规则时,需要注意以下行为差异:

  1. 或签测试

    • 场景:两个审批人(manager1, manager2)
    • 预期:任意一人审批通过后,其他待审批任务自动取消
    • 验证SQL:SELECT * FROM ACT_RU_TASK观察任务状态变化
  2. 比例签测试

    • 场景:三个审批人(hr1, hr2, hr3),设置通过比例为>30%
    • 预期:一人同意不足(33%),两人同意则通过(66%)
    • 关键日志:查看nrOfCompletedInstances值变化
  3. 会签测试

    • 场景:三个审批人(vp1, vp2, vp3)
    • 预期:必须全部审批通过,任一拒绝则流程终止
    • 异常处理:需要在ServiceTask中添加边界事件处理拒绝情况

4. 高级配置与性能优化

在实际企业应用中,我们还需要考虑以下高级配置和优化点:

4.1 并行与串行执行模式

多实例任务支持两种执行模式:

  • 并行(parallel):默认模式,所有审批任务同时创建
  • 串行(sequential):按顺序逐个创建审批任务

配置示例:

<bpmn:multiInstanceLoopCharacteristics camunda:collection="${approvers}" camunda:elementVariable="approver" isSequential="true"> ... </bpmn:multiInstanceLoopCharacteristics>

4.2 动态审批人分配

审批人列表可以通过表达式动态获取:

camunda:collection="${approvalService.getApprovers(execution)}"

对应的Java服务类:

@Component public class ApprovalService { public List<String> getApprovers(DelegateExecution execution) { String department = (String) execution.getVariable("department"); // 根��部门返回不同的审批人列表 return approverRepository.findByDepartment(department); } }

4.3 性能优化建议

当审批人数量较多时(如超过20人),需要考虑以下优化措施:

  1. 批量任务创建

    // 在流程引擎配置中设置批量大小 processEngineConfiguration.setBatchSize(10);
  2. 异步延续

    <bpmn:userTask id="mass_approval" camunda:asyncBefore="true"> <bpmn:multiInstanceLoopCharacteristics.../> </bpmn:userTask>
  3. 历史级别配置

    # 适当降低历史记录级别 camunda.history.level=audit

5. 常见问题排查指南

在实际开发中,可能会遇到以下典型问题:

问题1:审批任务没有按预期创建或完成
排查步骤

  1. 检查collection变量是否正确注入
  2. 验证表达式语法,特别是比较运算符
  3. 查看ACT_RU_TASK表确认任务是否创建

问题2:完成条件不生效
解决方案

  • 确保使用正确的实例计数变量:
    // 正确写法 ${nrOfCompletedInstances >= 1} // 错误写法(缺少Instances后缀) ${nrOfCompleted >= 1}

问题3:审批人变量传递错误
调试方法

  1. 在任务监听器中打印变量:
    execution.getVariables().forEach((k,v) -> System.out.println(k + "=" + v));
  2. 检查elementVariable名称是否与Assignee表达式一致

问题4:历史记录不完整
配置调整

<process id="leave_approval" camunda:historyTimeToLive="90"> ... </process>

通过这个请假审批流程的完整示例,相信你已经掌握了Camunda中多实例任务的三种审批规则实现方式。在实际项目中,可以根据业务需求灵活组合这些模式,构建出既符合业务流程又高效可靠的审批系统。

http://www.jsqmd.com/news/938534/

相关文章:

  • 从RTK到PPP:聊聊高精度定位的‘单兵作战’与‘集团军’模式,以及千寻、Hexagon的1分钟收敛是怎么做到的
  • 基于BD139晶体管与7812稳压的双通道LED闪烁灯设计与制作
  • 2026Q3 上海普陀家装甄选指南|老牌装企实测排行,从资质、报价、落地效果择优推荐 - 品牌优企推荐
  • Tessy工程迁移与复用实战:当.pdbx工程文件换了电脑或路径,如何快速恢复测试环境?
  • 自然语言控制电脑:UI-TARS-desktop如何重新定义人机交互范式
  • 北京老酒鉴定哪家靠谱?2026 上门收酒鉴定实力 TOP5 深度测评,打孔拔酒辨别干货 - 品牌排行榜单
  • 在VMware虚拟机里给银河麒麟V10 SP1 LiveCD加装Remmina远程桌面(海光CPU版)
  • Fastbot实战:如何用它精准‘轰炸’你App的搜索框和登录页?
  • 基于Arduino的模拟时钟学习盒:嵌入式系统与交互设计实践
  • AI写作工具实战指南:从流程拆解到人机协作,释放创作潜能
  • 别再只盯着压缩率了!聊聊嵌入式单片机里压缩算法的那些‘坑’:内存、实时性与代码复杂度
  • 2026年618好物有哪些推荐?精选十款超实用高口碑必买好物!全是精品
  • 别再只调PID了!用前馈控制大幅提升PMSM位置环跟踪性能(Simulink仿真对比)
  • 如何5分钟内打造百万DPS角色?PoeCharm汉化版终极指南
  • 别再手动量了!3DMAX里这个Smart Measure插件,5分钟搞定模型尺寸测量
  • 海南车灯升级天花板!海口澳兹姆麒麟车灯旗舰店 —— 超豪华车型专属改装,全岛规模TOP1正规门店 - 小熊打盹
  • 基于Arduino与p5.js的串行通信游戏控制器开发实战
  • Arduino与WS2812B打造儿童智能时钟:从硬件到软件的完整创客指南
  • 纸电路入门:从零制作会发光的惊喜贺卡,理解电路基本原理
  • Canvas-Editor协同编辑踩坑实录:从用户选区冲突到数据同步的那些‘坑’
  • PDFPatcher完全指南:5个简单技巧彻底解决PDF格式难题
  • T265+IMU标定结果怎么看?手把手教你解读Kalibr输出与坐标系转换
  • 创业者如何利用AI赋能商业创新:从市场洞察到运营提效
  • 从零构建蓝牙振动按钮:触觉反馈与无线控制的嵌入式实践
  • Unity 自定义包的 package.json 简单写法
  • 基于Arduino的智能泡茶机DIY:从硬件选型到状态机编程全解析
  • 不只是主题美化:用Oh My Zsh插件打造你的命令行‘外挂’工作流(附zsh-autosuggestions高阶配置)
  • 告别时序图恐惧!用STM32CubeMX和HAL库,5分钟搞定I2C驱动24C02 EEPROM
  • 避坑指南:DolphinScheduler 3.2.0集群部署,我踩过的那些权限和依赖的坑
  • 别再死记硬背了!用这5个钢琴/吉他实战片段,彻底搞懂乐理里的‘波音’怎么弹