当前位置: 首页 > 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.zskr.cn/news/1449910.html

相关文章:

  • 从RTK到PPP:聊聊高精度定位的‘单兵作战’与‘集团军’模式,以及千寻、Hexagon的1分钟收敛是怎么做到的
  • Arduino与VEX全向轮避障机器人:从硬件搭建到代码优化全解析
  • 北京老酒鉴定哪家靠谱?2026 上门收酒鉴定实力 TOP5 深度测评,打孔拔酒辨别干货 - 品牌排行榜单
  • Fastbot实战:如何用它精准‘轰炸’你App的搜索框和登录页?
  • AI写作工具实战指南:从流程拆解到人机协作,释放创作潜能
  • 别再只盯着压缩率了!聊聊嵌入式单片机里压缩算法的那些‘坑’:内存、实时性与代码复杂度
  • 2026年618好物有哪些推荐?精选十款超实用高口碑必买好物!全是精品
  • 如何5分钟内打造百万DPS角色?PoeCharm汉化版终极指南
  • 纸电路入门:从零制作会发光的惊喜贺卡,理解电路基本原理
  • 创业者如何利用AI赋能商业创新:从市场洞察到运营提效
  • 从零构建蓝牙振动按钮:触觉反馈与无线控制的嵌入式实践
  • 避坑指南:DolphinScheduler 3.2.0集群部署,我踩过的那些权限和依赖的坑
  • 告别时序图恐惧!用STM32CubeMX和HAL库,5分钟搞定I2C驱动24C02 EEPROM
  • 从摄像头模组到SoC:MIPI DPHY信号完整性(SI)问题排查全记录
  • 5个实战技巧:快速掌握Python通达信数据获取与分析
  • LabVIEW TCP通讯避坑指南:从‘能通’到‘稳定’的5个实战配置细节(附2024版范例)
  • 【Sora 2旅游视频爆款公式】:20年AI影像专家亲授3大生成逻辑、5类高转化脚本结构与避坑清单
  • 如何用3分钟精准计算AI提示词成本?TikTokenizer在线分词器终极指南
  • 基于ATtiny13A与PWM调光的超长续航智能手电筒设计与实现
  • 2026 漯河本地靠谱的GEO优化公司,AI搜索排名推荐榜(综合实力TOP5) - 星际AI
  • 别再只会搜IP了!手把手教你用ZoomEye的5个高级搜索语法,精准定位网络资产
  • 破解AI训练存储瓶颈:用MinIO构建高性能数据供给层
  • 告别调参玄学:用进化计算自动优化你的机器学习模型(附Python代码)
  • 2026树洞平台极致隐私测评:纯文字交互+银行级加密+本地存储=树洞安全最高标准 - 时时资讯
  • 云原生实践指南:从概念到落地的八项核心能力解析
  • 【Veo 2企业级应用白皮书】:已验证的12行业落地场景+合规水印嵌入方案(含GDPR适配指南)
  • STM32 SPI驱动W25Q64 Flash避坑指南:从软件模拟到硬件外设的完整实战
  • 论文重复率检测跟什么有关?
  • 20252921 2025-2026-2 《网络攻防实践》第10周作业
  • 如何用ok-ww实现鸣潮全自动挂机:从零开始的完整实战指南