告别 Flowable 28 张表的臃肿噩梦:7 张表搞定中国式复杂审批的国产轻量级工作流 Warm-Flow 深度实战

告别 Flowable 28 张表的臃肿噩梦:7 张表搞定中国式复杂审批的国产轻量级工作流 Warm-Flow 深度实战

告别 Flowable 28 张表的臃肿噩梦:7 张表搞定中国式复杂审批的国产轻量级工作流 Warm-Flow 深度实战

在企业级企业信息化与数字化中台系统的建设中,“审批流”几乎是绕不开的刚性需求。从常见的报销单审批、请假流转,到复杂的合同多级会签、加签撤回、退回任意节点,工作流引擎始终是业务架构的心脏。

然而,长期统治 Java 生态的工作流标准框架——Activiti、Flowable 与 Camunda,在带来标准化(BPMN 2.0)的同时,也为开发团队带来了难以承受的沉重负担:动辄 28 到 40 多张底层物理表、极其复杂的 XML 格式规范、难以捉摸的监听器生命周期,以及面对国内特有的“转办、会签、委派、驳回至指定人”等“中国式审批”场景时抓襟见肘的二次开发成本。

传统工作流与 Warm-Flow 架构对比

难道实现一个业务工作流,真的需要把系统搞得如此臃肿复杂吗?Dromara 开源社区孵化的国产轻量级工作流引擎 Warm-Flow(暖流) 给出了颠覆性的答案:仅用 7 张表,零 BPMN 学习成本,原生支持中国特色审批场景! 本文将从底层架构原理、表结构剖析、Spring Boot 3 集成实战到复杂审批逻辑演练,带你彻底搞懂并驾驭这款极简工作流引擎。


一、痛点反思:传统 BPMN 引擎为何成为团队的技术负债?

要理解 Warm-Flow 的价值,我们必须先看清传统工作流引擎(如 Flowable / Activiti)在日常业务系统中的几大痛点:

1. 表结构极其膨胀,排查运维宛如天书

Flowable 初始化后会建立多达 28+ 张 ACT_* 开头的系统表(包括 ACT_RU_* 运行时表、ACT_HI_* 历史表、ACT_RE_* 资源库表、ACT_GE_* 通用表等)。当线上发生一个卡单或节点卡死问题时,排障人员常常需要在 ACT_RU_TASK、ACT_RU_EXECUTION、ACT_RU_IDENTITYLINK 之间反复 JOIN,关联查询痛苦不堪。

2. 标准 BPMN 2.0 的“水土不服”

BPMN 2.0 是国际标准的工业流程建模规范,设计初衷是涵盖跨系统通信、补偿事务、事件网关等全量业务流程。但国内 90% 的企业办公场景本质上只是“以人为中心的任务流转(Human Task Flow)”。BPMN 中严苛的网关规则使得简单的“驳回上一节点”或“任意退回”都需要开发人员手写复杂的命令树(Command Executor)或操作 Execution 指针,极易引发死锁和数据不一致。

3. ORM 框架强绑定与侵入性过强

多数成熟 BPMN 引擎底层死死绑定在 MyBatis 原始 XML 体系上,在团队广泛拥抱 MyBatis-Plus、Spring Data JPA 甚至无实体持久层(如 Solon、Flex)时,无法实现无缝的语法统一与分页拦截复用。


二、Warm-Flow 核心设计:7 张表如何构建完整工作流闭环?

Warm-Flow 抛弃了晦涩沉重的 BPMN 2.0 规范,基于状态机(State Machine)思想,采用高内聚低耦合的数据模型。整套引擎仅依赖 7 张精简数据表,逻辑层次清晰分明:

Warm-Flow 核心执行状态机与节点调度架构

告别 Flowable 28 张表的臃肿噩梦:7 张表搞定中国式复杂审批的国产轻量级工作流 Warm-Flow 深度实战

7 张核心表职责矩阵:

表名 中文定义 业务职责与生命周期
flow_definition 流程定义表 存储流程模版基础信息(编码、名称、状态、分类等)
flow_node 流程节点表 存储节点配置(开始、审批节点、网关分支、结束节点、审批人配置)
flow_skip 流程跳转条件表 定义节点间的连接线与流转规则(支持 SpEL 表达式过滤)
flow_instance 流程实例表 存储运行中的业务流程主记录(业务主键、当前状态、发起人、耗时)
flow_task 待办任务表 存储当前需要人工或系统处理的活动任务(执行人、任务状态)
flow_his_task 历史任务记录表 归档所有已流转完毕的任务快照(包含审批意见、处理人、操作时间)
flow_user 流程权限人表 存储流程设计期与运行时的候选人、候选组(支持部门、角色多维权限绑定)

从上表可以看出:3 张表管理静态设计期(Definition/Node/Skip),3 张表管理动态运行时(Instance/Task/HisTask),1 张表管理用户关联(User)。没有繁琐的中间层,开发人员甚至用 Navicat 看一眼表数据,就能对全流程的运行状态一目了然!


三、Spring Boot 3 + Warm-Flow 极速落地实战

接下来,我们以一套标准的请假报销审批流为例,演示如何在 Spring Boot 3 工程中 10 分钟集成并运行 Warm-Flow。

1. 引入依赖与配置

在 Maven pom.xml 中引入 warm-flow-plugin-modes-sb 依赖(内置适配 MyBatis-Plus):

<dependencies>
<!-- Warm-Flow Spring Boot Starter -->
<dependency>
<groupId>org.dromara.warm</groupId>
<artifactId>warm-flow-mybatis-plus-sb-starter</artifactId>
<version>1.3.4</version>
</dependency>

<!-- 支持 SpEL 表达式计算 -->
<dependency>
<groupId>org.dromara.warm</groupId>
<artifactId>warm-flow-expression-spel</artifactId>
<version>1.3.4</version>
</dependency>

<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>3.5.7</version>
</dependency>
</dependencies>

在 application.yml 中开启自动建表:

warm-flow:
# 开启启动时自动初始化建表与升级
auto-ddl: true
# 表达式类型选择 SpEL
expression-type: spel

2. 流程定义装配(代码化定义或 JSON/Web 驱动)

除了使用官方配套的仿钉钉/飞书前端低代码设计器外,后端开发者可以直接通过 API 或 JSON 定义流程节点与跳转规则:

package com.skillup.warmflow.service;

import org.dromara.warm.flow.core.dto.FlowCombine;
import org.dromara.warm.flow.core.entity.Definition;
import org.dromara.warm.flow.core.entity.Node;
import org.dromara.warm.flow.core.entity.Skip;
import org.dromara.warm.flow.core.service.DefService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class WorkflowDeployService {

@Autowired
private DefService defService;

public void deployReimbursementFlow() {
FlowCombine combine = new FlowCombine();

// 1. 流程主定义
Definition def = defService.newDef();
def.setFlowCode("leave_reimbursement");
def.setFlowName("请假与报销审批流");
def.setVersion("1.0.0");
def.setIsPublish(1); // 立即发布生效
combine.setDefinition(def);

// 2. 装配节点:开始 -> 主管审批 -> 财务审批 -> 结束
List<Node> nodeList = new ArrayList<>();
Node startNode = createNode("start", "发起人提交", "start", null);
Node managerNode = createNode("manager_audit", "部门经理审批", "between", "manager_role");
Node financeNode = createNode("finance_audit", "财务总监审批", "between", "finance_role");
Node endNode = createNode("end", "流程归档", "end", null);

nodeList.add(startNode);
nodeList.add(managerNode);
nodeList.add(financeNode);
nodeList.add(endNode);
combine.setAllNodes(nodeList);

// 3. 装配跳转连线与条件(支持 SpEL 判断金额)
List<Skip> skipList = new ArrayList<>();
// start -> manager
skipList.add(createSkip("start", "manager_audit", "提交", null));

// manager -> finance (金额 > 1000 元需要财务审批)
skipList.add(createSkip("manager_audit", "finance_audit", "转入财务", "#{amount > 1000}"));

// manager -> end (金额 <= 1000 元经理审批完直接结束)
skipList.add(createSkip("manager_audit", "end", "直接归档", "#{amount <= 1000}"));

// finance -> end
skipList.add(createSkip("finance_audit", "end", "财务归档", null));

combine.setAllSkips(skipList);

// 部署入库
defService.insertFlowCombine(combine);
System.out.println(">>> 流程 [leave_reimbursement] 部署成功!");
}

private Node createNode(String code, String name, String type, String permission) {
Node node = defService.newNode();
node.setNodeCode(code);
node.setNodeName(name);
node.setNodeType(type);
if (permission != null) {
node.setPermissionFlag(List.of(permission));
}
return node;
}

private Skip createSkip(String nowCode, String nextCode, String name, String expr) {
Skip skip = defService.newSkip();
skip.setNowNodeCode(nowCode);
skip.setNextNodeCode(nextCode);
skip.setSkipName(name);
skip.setSkipType("PASS");
skip.setExpr(expr);
return skip;
}
}

3. 核心流转:发起、审批、条件分支流转

在业务 Controller 中注入 InsService(实例服务)与 TaskService(任务服务):

package com.skillup.warmflow.service;

import org.dromara.warm.flow.core.dto.FlowParams;
import org.dromara.warm.flow.core.entity.Instance;
import org.dromara.warm.flow.core.service.InsService;
import org.dromara.warm.flow.core.service.TaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

@Service
public class LeaveApprovalService {

@Autowired
private InsService insService;

@Autowired
private TaskService taskService;

/**
* 发起申请
*/
public Long submitLeave(String userId, String businessId, double amount) {
Map<String, Object> variables = new HashMap<>();
variables.put("amount", amount);
variables.put("submitter", userId);

FlowParams params = FlowParams.build()
.flowCode("leave_reimbursement")
.createBy(userId)
.variable(variables);

// 启动流程实例,业务主键绑定 businessId
Instance instance = insService.start(businessId, params);
System.out.println("流程启动成功,实例ID: " + instance.getId());
return instance.getId();
}

/**
* 经理审批并流转
*/
public void managerApprove(Long taskId, String managerId, boolean pass, String comment) {
FlowParams params = FlowParams.build()
.createBy(managerId)
.message(comment);

if (pass) {
// 通过当前节点,自动计算 SpEL 分支跳转
taskService.skip(taskId, params);
System.out.println("经理审批通过,流转下一节点");
} else {
// 驳回至开始节点或指定节点
taskService.termination(taskId, params);
System.out.println("经理驳回,流程终止");
}
}
}

四、中国式复杂审批特性:会签、委派、任意退回

Warm-Flow 在设计之初就深度考虑了国内办公自动化场景的特殊性:

1. 票签与会签(Countersign)

在传统 BPMN 中,多实例(Multi-Instance)会签是无数初学者的噩梦。Warm-Flow 原生提供多种表决策略: - 百分比票签(Percentage):例如当同意人数达到 70% 时自动推进; - 全票通过(All Pass):只要有一票拒绝立即终止; - 一人即过(Any Pass):类似或签机制。

只需在节点配置 collaborativeHandler 或会签属性,引擎自动在 flow_task 中管理子任务并汇总结果。

2. 任意退回(Any Node Return)

在审批过程中,领导常常提出“退回给发起人修改”,甚至“财务退回给经理重新审核”。 Warm-Flow 提供一行 API:

// 退回到指定前置节点 code
taskService.back(taskId, FlowParams.build().skipType("REJECT").nodeCode("start"));

引擎自动清除中间活动任务,恢复目标节点的待办状态,并将历史记录完整归档到 flow_his_task。


五、架构全维度基准选型对比

核心指标 Activiti / Flowable 6.x Camunda 7/8 Warm-Flow 1.3+
底层核心表数量 28 ~ 42 张 30+ 张 (Camunda 8 引入 Zeebe) 仅 7 张表
JAR 依赖体积 ~18 MB ~25 MB < 1.5 MB
启动耗时 3.5s ~ 7.0s 4.0s ~ 8.0s 0.2s 极速冷启动
国内审批特性支持 需深度定制扩展 Command 需二次开发 开箱即用(驳回、加签、减签)
持久层适配 MyBatis XML 强绑定 MyBatis / 自研 Engine 适配 MyBatis-Plus / JPA / Solon
学习门槛 高(BPMN 2.0 规范体系) 极高(Zeebe 分布式流) 极低(30分钟掌握全部 API)

六、总结与实操练习指引

工作流引擎的核心价值在于服务业务流转,而非制造技术壁垒。Warm-Flow 用 7 张表重新定义了国产 Java 工作流的优雅与精巧,无论是中小型 SaaS 产品、企业内部 OA 办公流,还是高吞吐的微服务调度,它都展现出了极强的适应力与维护幸福感。

为了让大家零门槛验证 Warm-Flow 的完整能力,我们整理了配套的完整实战工程源码,包含 Spring Boot 3 工程、内置 H2 嵌入式数据库、初始化表结构脚本与完整的审批流转单元测试用例:

💻 配套实训环境与动手练习

本文涉及的相关技术指令、开发环境与工具链已内置在边学边练在线实验室中,无需繁琐安装配置,随时在浏览器中实践体验:

文章版权声明:除非注明,否则均为边学边练网络文章,版权归原作者所有

最新文章

热门文章

本栏目文章