工作流(3)——复杂工作流:从驳回、加签到会签

引言

在上一篇中,我们从底层架构拆解了工作流引擎的执行机制(Execution流转)与持久化机制(数据库状态机)。在标准的 BPMN 2.0 规范下,流程是高度结构化且单向向前的。

但在真实的业务场景中,流程绝不仅仅是"同意"和"下一步"。业务人员会提出大量打破常规流转规则的需求。本篇将直接抛弃比喻,纯粹从技术实现与底层 API 出发,直面工作流开发中最棘手的四大问题,并给出破局方案。

1 复杂工作流的破局之道:从驳回、加签到会签

1.1 业务痛点

流程定义为 A(发起) -> B(部门主管) -> C(总监) -> D(财务)

当流程流转到 D 时,财务发现单据有问题,要求直接打回给 B 修改,或者打回给 A 重新发起。

BPMN 2.0 规范中并没有原生的"驳回"连线,如果在画图时将每个节点都连一条线回到起点,会导致流程图极其混乱(面条图),且无法维护。

1.2 技术解析

工作流引擎的核心是维护 Execution(执行实例)在 Activity(节点)之间的位置。向前流转是引擎解析连线(Sequence Flow)自动计算的。要实现向后跳转,我们需要跳过连线解析,直接通过 API 强行修改 Execution 的当前指针位置。

1.3 解决方案(以 Flowable 为例)

现代开源引擎(如 Flowable 6.x)提供了专门的节点跳转 API:ChangeActivityStateBuilder

  1. 获取当前节点与目标节点:通过 API 获取当前正在执行的任务节点 ID,以及需要驳回到的目标节点 ID
  2. 清理当前状态:引擎需要先作废当前节点产生的所有待办任务(Task),并清理当前节点作用域内的局部变量
  3. 指针转移 :通过 API 直接将 Execution 的指针移动到目标节点
  4. 触发执行:引擎在目标节点重新触发进入逻辑,生成新的待办任务

核心代码逻辑:

java 复制代码
// 使用 Flowable 原生 API 实现跳转
runtimeService.createChangeActivityStateBuilder()
    .processInstanceId(processInstanceId)
    .moveActivityIdTo(currentActivityId, targetActivityId) // 从当前节点跳到目标节点
    .changeState();

注意:在执行跳转前,通常需要往历史表中写入一条自定义的批注(Comment),记录"由节点D驳回至节点B,原因:发票不符",以保证审计记录的完整性。

2 问题二:审批人需要临时增加人员,如何实现"动态加签"?

2.1 业务痛点

流程定义中,当前节点是"技术总监审批"。但在实际审批时,技术总监认为这个方案涉及安全问题,需要临时让"安全总监"先审批,或者和"安全总监"一起审批。这个"安全总监"在原流程图中根本不存在。

2.2 技术解析

这涉及两种不同的加签模式,底层处理逻辑完全不同:

  1. 前加签(顺序执行):安全总监先批,批完再还给技术总监
  2. 并签(并行执行):安全总监和技术总监同时审批,两人都同意才算过

2.3 解决方案

2.3.1 场景A:前加签(基于任务委派 Delegation)

引擎原生支持任务的委派。技术总监不直接完成任务,而是调用 taskService.delegateTask(taskId, "安全总监")

此时,底层表 ACT_RU_TASK 中该任务的 ASSIGNEE_(处理人)会变成安全总监,而 OWNER_(所有者)保留为技术总监,任务状态变为 PENDING

安全总监处理完成后,调用 taskService.resolveTask(taskId),任务处理人会自动切回技术总监,流程并没有往下走,完美实现前加签。

2.3.2 场景B:并签(基于多实例动态扩展)

如果要在运行时增加一个并行任务,直接 new Task() 插入数据库是极其危险的,因为独立生成的任务脱离了 Execution 的生命周期管控,完成后无法触发流程继续。

正确的做法是:将该节点在画图时配置为"多实例(Multi-Instance)"节点

当需要动态加签时,通过调用引擎的多实例扩展 API:

java 复制代码
// 动态向多实例节点中追加一个执行实例和任务
runtimeService.addMultiInstanceExecution(
    activityId, 
    processInstanceId, 
    Collections.singletonMap("assignee", "安全总监")
);

引擎会基于当前节点的配置,动态分裂出一个新的 Execution 并生成对应的任务,统一纳入多实例的完成条件计算中。

3 问题三:"5人中3人同意即可",如何实现复杂的"会签/或签"逻辑?

3.1 业务痛点

一个评审节点由 5 名专家组成。业务规则不是"全部同意才通过",而是"只要有 3 人同意即通过";或者"只要有 1 人拒绝,直接一票否决,流程结束"。

3.2 技术解析

在标准节点中,一个任务完成,流程就走向下一步。针对多人审批,必须使用 多实例(Multi-Instance) 节点。

引擎在运行多实例时,会在内部维护三个极其重要的内置变量:

  • nrOfInstances:总实例数(比如 5)
  • nrOfCompletedInstances:已完成的实例数
  • nrOfActiveInstances:当前活动的实例数

3.3 解决方案:基于完成条件(Completion Condition)的表达式注入

在流程定义的 XML 中,为多实例节点配置 <completionCondition> 标签。引擎在每一次单个任务完成时,都会计算这个表达式。如果结果为 true,引擎会立刻销毁剩余未完成的实例,并驱动流程走向下一个节点。

3.3.1 实现"3人同意即通过"

配置表达式:${nrOfCompletedInstances >= 3}

当第 3 个人点击同意并完成任务时,表达式返回 true,剩下的 2 个待办任务会被引擎物理删除,流程进入下一环节。

3.3.2 实现"一票否决"

  1. 任何人在点击"拒绝"时,通过 API 向引擎注入一个局部变量:taskService.setVariableLocal(taskId, "isVeto", true)
  2. 配置完成条件表达式:${isVeto == true || nrOfCompletedInstances == nrOfInstances}
  3. 只要有人触发了否决变量,表达式立即成立,多实例结束。随后在节点后方连接一个排他网关(Exclusive Gateway),根据 isVeto 的值路由到结束节点

4 问题四:发起人点错提交了,如何实现"流程撤回"?

4.1 业务痛点

员工发起请假单,流程已经流转到了部门主管。员工发现天数填错了,想要撤回单据重新修改。

4.2 技术解析

撤回本质上是一种附带条件限制的特定节点跳转 。它与"驳回"的技术实现完全一致(都是通过修改 Execution 指针实现),区别在于业务校验逻辑

4.3 解决方案:严格的校验前置 + 跳转 API

  1. 状态校验 :撤回操作必须在后端进行严格的校验。查询当前流程实例的活动任务列表(taskService.createTaskQuery())。如果目标任务已经被主管签收(Claim)完成(Complete),则抛出业务异常,拒绝撤回
  2. 执行跳转 :如果主管还未处理,调用与"驳回"相同的 ChangeActivityStateBuilder API,将 Execution 从主管节点强制拉回到"开始节点"或专门的"草稿节点"
  3. 数据清理 :撤回后,业务系统需将自身业务表(如 leave_request)的状态从"审批中"更新回"草稿",并允许用户修改表单数据

5 总结

通过对以上四个高频复杂问题的拆解,我们可以得出一个关于工作流引擎的核心结论:

工作流引擎不仅是一套严格遵守 BPMN 规范的解析器,更是一个提供底层状态机操作 API 的基础平台。

面对复杂的业务需求,单纯依靠画图(配置)是无法解决所有问题的。架构师和开发者必须跳出"连线流转"的思维局限,深刻理解 Execution(执行实例)、Task(任务)、Variable(变量)之间的关系,通过代码调用引擎提供的干预 API(如跳转、委派、多实例动态干预),结合业务系统自身的逻辑校验,才能构建出既规范又灵活的企业级工作流中台。

掌握了这些,你就不再只是一个"会用框架调 API 的码农",而是真正具备了掌控复杂流转系统底层逻辑的架构能力。

相关推荐
ZGi.ai3 天前
审批一直没人处理,Workflow 怎么做超时升级?
工作流·智能体·审批流程·任务自动化·zgi·超时升级
ZGi.ai5 天前
不同请求走不同流程,ZGI Workflow 怎么配?
工作流·智能体·变量管理·zgi·条件分支
ZGi.ai6 天前
知识库权限变了,怎样避免答错?
agent·权限管理·知识库·工作流·zgi·客服运营
ZGi.ai6 天前
工作流失败后,怎样快速定位?
工作流·故障排查·知识管理·模型管理·zgi·agentruntime
凤山老林6 天前
Spring Boot 整合 Flowable 的企业级落地指南
数据库·spring boot·后端·flowable·工作流
ShallWeL9 天前
【Agent工程】(15)—— 评测集与回归门禁
人工智能·agent·工作流
AI工具人PM产品经理10 天前
Claude Code TDD 实战:84 个测试护体的 spec→plan 开发流
jest·tdd·工作流·ai 编程·claude code
ShallWeL12 天前
RAG Embedding 模型替换与索引回归
人工智能·embedding·知识库·工作流·rag
2601_9620973614 天前
Python工作流实战:SpiffWorkflow深度应用与BPMN自动化指南
python·自动化·工作流·bpmn·spiffworkflow
ShallWeL14 天前
RAG 向量索引重建与回归
人工智能·agent·知识库·工作流·rag