从0到1精通Warm-Flow:国产轻量级工作流引擎实战指南
引言:工作流引擎的选型困境与破局之道
你是否正在为项目寻找一款既轻量又强大的工作流引擎?面对市场上纷繁复杂的选择,是否感到无从下手?要么是过于庞大笨重,集成困难;要么是功能简陋,无法满足实际业务需求。今天,我们将带你深入了解一款国产优秀工作流引擎——Warm-Flow,它以简洁轻量、五脏俱全、灵活扩展性强的特点,正在成为众多开发者的首选。
读完本文,你将获得:
- Warm-Flow工作流引擎的核心特性与优势解析
- 从零开始的环境搭建与快速集成指南
- 经典与仿钉钉双模式设计器的全面使用教程
- 常见审批场景的实战案例与实现代码
- 高级功能如监听器、表达式的应用技巧
- 性能优化与扩展开发的最佳实践
1. Warm-Flow简介:国产工作流引擎的崛起
1.1 什么是Warm-Flow?
Warm-Flow是Dromara社区推出的一款国产工作流引擎(Workflow Engine),它以简洁轻量、功能全面、扩展性强为主要特点。作为一款面向开发者的中间件,Warm-Flow可以帮助你快速构建企业级的流程审批系统,如请假流程、报销审批、公文流转等各类业务流程。
1.2 Warm-Flow的核心优势
Warm-Flow相比其他工作流引擎,具有以下显著优势:
| 优势 | 说明 |
|---|---|
| 简洁轻量 | 核心仅7张表,代码量少,学习曲线平缓 |
| 易于集成 | 通过jar包快速集成,支持Spring和Solon框架 |
| 双模式设计器 | 原生支持经典模式和仿钉钉模式,满足不同用户习惯 |
| 功能全面 | 支持各种复杂审批操作和高级特性 |
| 灵活扩展 | 提供丰富的扩展点,可定制满足特定业务需求 |
| 多框架支持 | 兼容多种ORM框架和数据库 |
| 国产开源 | 完全开源免费,活跃的社区支持 |
1.3 技术架构概览
Warm-Flow的整体架构如下:
graph TD
A[应用系统] --> B[Warm-Flow核心引擎]
B --> C[流程定义管理]
B --> D[流程实例运行]
B --> E[任务分配与办理]
B --> F[历史记录管理]
B --> G[表单引擎]
B --> H[权限控制]
C --> I[设计器集成]
D --> J[流程执行器]
J --> K[节点处理器]
J --> L[网关处理器]
J --> M[监听器]
J --> N[表达式引擎]
B --> O[ORM适配器]
O --> P[MyBatis]
O --> Q[MyBatis-Plus]
O --> R[JPA]
O --> S[其他ORM框架]
O --> T[数据库]
2. 环境搭建:从零开始的集成之旅
2.1 准备工作
在开始集成Warm-Flow之前,请确保你的开发环境满足以下要求:
- JDK 8+
- Maven 3.5+
- 支持的数据库(MySQL、Oracle、PostgreSQL、SQL Server等)
- Spring Boot 2.x/3.x 或 Solon 1.x/2.x(根据项目需求选择)
2.2 获取源代码
Warm-Flow的源代码托管在GitCode上,你可以通过以下命令克隆仓库:
git clone https://gitcode.com/dromara/warm-flow.git
2.3 数据库初始化
Warm-Flow需要一些基础表结构来存储流程定义、实例、任务等数据。根据你使用的数据库类型,执行相应的SQL脚本:
- 进入项目的
sql目录,选择对应数据库的子目录 - 执行全量脚本
warm-flow-all.sql
例如,对于MySQL数据库:
cd warm-flow/sql/mysql
# 执行warm-flow-all.sql脚本
如果你是升级版本,只需执行对应版本的升级脚本:
cd warm-flow/sql/mysql/v1-upgrade
# 执行对应版本的升级脚本,如warm-flow_1.8.0.sql
2.4 项目集成
2.4.1 Maven依赖
在你的项目pom.xml中添加Warm-Flow的依赖。根据你使用的ORM框架和Spring版本选择合适的starter:
Spring Boot + MyBatis-Plus
<dependency>
<groupId>org.dromara.warm</groupId>
<artifactId>warm-flow-mybatis-plus-sb-starter</artifactId>
<version>最新版本</version>
</dependency>
Spring Boot 3 + MyBatis
<dependency>
<groupId>org.dromara.warm</groupId>
<artifactId>warm-flow-mybatis-sb3-starter</artifactId>
<version>最新版本</version>
</dependency>
Solon + MyBatis-Plus
<dependency>
<groupId>org.dromara.warm</groupId>
<artifactId>warm-flow-mybatis-plus-solon-plugin</artifactId>
<version>最新版本</version>
</dependency>
2.4.2 配置文件
在application.yml或application.properties中添加Warm-Flow的配置:
warm:
flow:
# 是否开启调试模式
debug: false
# 流程设计器是否启用
designer:
enabled: true
# ORM配置
orm:
type: mybatis-plus # 可选值:mybatis, mybatis-plus, jpa, easy-query, mybatis-flex
# 多租户配置
tenant:
enabled: false
column: tenant_id
# 软删除配置
logic-delete:
enabled: false
column: is_deleted
value: 1
not-value: 0
2.4.3 启动类配置
在Spring Boot启动类上添加@EnableWarmFlow注解:
import org.dromara.warm.flow.spring.annotation.EnableWarmFlow;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableWarmFlow
public class YourApplication {
public static void main(String[] args) {
SpringApplication.run(YourApplication.class, args);
}
}
3. 设计器使用:双模式流程设计详解
Warm-Flow提供了两种流程设计模式:经典模式和仿钉钉模式,满足不同用户的使用习惯。
3.1 设计器集成
Warm-Flow的设计器通过jar包形式集成到你的项目中,无需单独部署。集成后,你可以通过访问以下地址打开设计器:
http://localhost:8080/warm-flow/designer/index.html
3.2 经典模式设计器
经典模式采用传统的流程图设计方式,适合技术人员使用。主要元素包括:
- 开始节点(Start Node):流程的起点
- 结束节点(End Node):流程的终点
- 任务节点(Task Node):需要用户处理的节点
- 网关(Gateway):控制流程走向的节点,包括排他网关、并行网关等
- 连接线(Sequence Flow):连接各个节点的线条
flowchart TD
start[开始] --> task1[部门经理审批]
task1 --> gateway{金额是否大于1000}
gateway -->|是| task2[财务经理审批]
gateway -->|否| task3[财务专员处理]
task2 --> end[结束]
task3 --> end
3.3 仿钉钉模式设计器
仿钉钉模式采用表单化的设计方式,更贴近业务人员的使用习惯,类似钉钉的审批流程设计。
主要功能包括:
- 审批人设置:支持指定成员、角色、发起人自选等多种方式
- 条件分支:根据条件设置不同的审批路径
- 高级设置:包括审批方式(会签/或签)、超时设置、提醒规则等
graph LR
A[发起人] --> B[直接上级审批]
B --> C{金额>1000}
C -->|是| D[财务总监审批]
C -->|否| E[财务专员审批]
D --> F[结束]
E --> F
3.4 流程定义的导出与导入
设计完成后,你可以将流程定义导出为JSON格式保存,也可以导入已有的流程定义JSON文件。
导出的JSON示例:
{
"flowId": "expense_approval",
"flowName": "费用报销审批流程",
"flowType": "NORMAL",
"version": 1,
"status": "ACTIVE",
"nodes": [
{
"nodeId": "start",
"nodeName": "开始",
"nodeType": "START",
"nextNodeId": "dept_manager"
},
{
"nodeId": "dept_manager",
"nodeName": "部门经理审批",
"nodeType": "TASK",
"assigneeType": "ROLE",
"assigneeValue": "DEPT_MANAGER",
"nextNodeId": "gateway"
},
// 更多节点...
],
"conditions": [
{
"conditionId": "cond1",
"nodeId": "gateway",
"expression": "${amount > 1000}",
"targetNodeId": "finance_manager"
},
// 更多条件...
]
}
4. 核心API:流程引擎的使用方法
Warm-Flow提供了简洁易用的API,帮助你快速实现流程的部署、启动、办理等操作。
4.1 FlowEngine核心接口
FlowEngine是Warm-Flow的核心接口,提供了流程操作的主要方法:
public interface FlowEngine {
// 部署流程定义
String deploy(FlowDeployDto flowDeployDto);
// 启动流程实例
String startInstance(FlowStartDto flowStartDto);
// 办理任务
void completeTask(FlowCompleteDto flowCompleteDto);
// 退回任务
void backTask(FlowBackDto flowBackDto);
// 获取待办任务列表
List<TaskDto> getTodoTasks(TaskQueryDto queryDto);
// 获取流程实例详情
InstanceDto getInstanceDetail(String instanceId);
// 生成流程图URL
String generateFlowImageUrl(String instanceId);
// 更多方法...
}
4.2 流程部署与启动
@Autowired
private FlowEngine flowEngine;
// 部署流程
public String deployFlow() {
FlowDeployDto deployDto = new FlowDeployDto();
deployDto.setFlowName("费用报销流程");
deployDto.setFlowKey("expense_approval");
deployDto.setCategory("财务");
// 流程定义JSON
deployDto.setFlowJson(flowJson);
return flowEngine.deploy(deployDto);
}
// 启动流程实例
public String startFlowInstance() {
FlowStartDto startDto = new FlowStartDto();
startDto.setFlowKey("expense_approval");
startDto.setBusinessKey("EXP-20230914-001"); // 业务关联ID
startDto.setInitiator("zhangsan"); // 发起人
// 设置流程变量
Map<String, Object> variables = new HashMap<>();
variables.put("amount", 1500); // 报销金额
variables.put("reason", "业务招待"); // 报销事由
startDto.setVariables(variables);
return flowEngine.startInstance(startDto);
}
4.3 任务办理与流转
// 办理任务
public void completeTask() {
FlowCompleteDto completeDto = new FlowCompleteDto();
completeDto.setTaskId("task123456"); // 任务ID
completeDto.setOperator("lisi"); // 操作人
completeDto.setAction("PASS"); // 操作:通过
// 审批意见
completeDto.setComment("同意报销,请财务处理");
// 任务变量
Map<String, Object> variables = new HashMap<>();
variables.put("approveDate", new Date());
completeDto.setVariables(variables);
flowEngine.completeTask(completeDto);
}
// 获取待办任务
public List<TaskDto> getTodoTasks() {
TaskQueryDto queryDto = new TaskQueryDto();
queryDto.setAssignee("wangwu"); // 办理人
return flowEngine.getTodoTasks(queryDto);
}
5. 实战案例:常见审批场景实现
5.1 请假流程
5.1.1 流程设计
请假流程通常包括以下步骤:
- 员工提交请假申请
- 直接上级审批
- 根据请假天数判断是否需要部门经理审批
- 人事部门备案
flowchart TD
start[开始] --> submit[员工提交申请]
submit --> leader[直接上级审批]
leader --> gateway{天数>3天}
gateway -->|是| manager[部门经理审批]
gateway -->|否| hr[人事备案]
manager --> hr
hr --> end[结束]
5.1.2 实现代码
// 启动请假流程
public String startLeaveProcess(LeaveRequest request) {
FlowStartDto startDto = new FlowStartDto();
startDto.setFlowKey("leave_approval");
startDto.setBusinessKey(request.getId().toString());
startDto.setInitiator(request.getApplicantId());
Map<String, Object> variables = new HashMap<>();
variables.put("leaveType", request.getLeaveType());
variables.put("days", request.getDays());
variables.put("startDate", request.getStartDate());
variables.put("endDate", request.getEndDate());
variables.put("reason", request.getReason());
startDto.setVariables(variables);
return flowEngine.startInstance(startDto);
}
// 审批处理
public void approveLeave(String taskId, String userId, boolean approved, String comment) {
FlowCompleteDto completeDto = new FlowCompleteDto();
completeDto.setTaskId(taskId);
completeDto.setOperator(userId);
completeDto.setAction(approved ? "PASS" : "REJECT");
completeDto.setComment(comment);
flowEngine.completeTask(completeDto);
}
5.2 报销审批流程
5.2.1 流程设计
报销审批流程通常根据金额大小设置不同的审批级别:
- 员工提交报销申请
- 部门经理审批
- 根据金额判断是否需要财务经理审批
- 财务处理付款
flowchart TD
start[开始] --> submit[员工提交报销申请]
submit --> deptLeader[部门经理审批]
deptLeader --> gateway{金额>10000}
gateway -->|是| financeManager[财务经理审批]
gateway -->|否| financeStaff[财务专员处理]
financeManager --> financeStaff
financeStaff --> end[结束]
5.2.2 实现代码
// 获取报销流程的待办任务
public List<TaskDto> getExpenseTodoTasks(String userId) {
TaskQueryDto queryDto = new TaskQueryDto();
queryDto.setAssignee(userId);
queryDto.setFlowKey("expense_approval");
return flowEngine.getTodoTasks(queryDto);
}
// 财务处理付款
public void processPayment(String taskId, String userId, String paymentNo) {
FlowCompleteDto completeDto = new FlowCompleteDto();
completeDto.setTaskId(taskId);
completeDto.setOperator(userId);
completeDto.setAction("PASS");
Map<String, Object> variables = new HashMap<>();
variables.put("paymentNo", paymentNo);
variables.put("paymentDate", new Date());
completeDto.setVariables(variables);
flowEngine.completeTask(completeDto);
}
6. 高级特性:监听器与表达式应用
6.1 监听器(Listener)
监听器允许你在流程执行的特定事件发生时执行自定义逻辑。Warm-Flow支持多种类型的监听器:
- 流程监听器:在流程实例的开始、结束等事件触发
- 任务监听器:在任务创建、完成等事件触发
- 执行监听器:在流程执行到特定节点时触发
6.1.1 监听器实现
@Component
public class ExpenseListener implements ExecutionListener {
@Autowired
private NotificationService notificationService;
@Override
public void notify(ExecutionListenerContext context) {
// 获取流程变量
Map<String, Object> variables = context.getVariables();
String instanceId = context.getInstanceId();
String nodeId = context.getNodeId();
// 发送通知
if ("dept_manager".equals(nodeId)) {
String assignee = context.getTask().getAssignee();
notificationService.send(assignee, "有新的报销单需要您审批", "流程实例ID: " + instanceId);
}
}
}
6.1.2 在设计器中配置监听器
在流程设计器中,选择需要添加监听器的节点,在属性面板中配置监听器:
- 监听器类型:选择"执行监听器"
- 事件类型:选择"节点进入"或"节点离开"
- 监听器实现:选择自定义的监听器类
6.2 表达式(Expression)
Warm-Flow支持使用表达式来动态计算流程变量、条件判断等。
6.2.1 变量表达式
在流程定义中,可以使用变量表达式来动态设置任务办理人、条件判断等:
${assignee} // 获取assignee变量
${initiator.deptManager} // 获取发起人部门经理
${amount > 1000} // 判断金额是否大于1000
6.2.2 SpEL表达式支持
Warm-Flow还支持Spring EL表达式,可以调用Bean的方法:
${@userService.getManager(initiator)} // 调用userService的getManager方法
${@tool.calculateTax(amount)} // 调用工具类计算税额
6.2.3 条件表达式应用
在网关的条件判断中使用表达式:
// 排他网关条件设置
ConditionDto condition = new ConditionDto();
condition.setNodeId("gateway1");
condition.setExpression("${amount > 1000}");
condition.setTargetNodeId("finance_manager");
7. 性能优化:大规模流程应用的调优策略
7.1 数据库优化
- 索引优化:为常用查询字段建立索引,如流程实例ID、业务键、办理人等
- 分表策略:对于历史数据,可以考虑按时间分表存储
- 批量操作:使用批量插入、更新减少数据库交互次数
7.2 缓存策略
- 流程定义缓存:缓存常用的流程定义,减少数据库查询
- 流程变量缓存:对频繁访问的流程变量进行缓存
- 缓存清理:合理设置缓存过期时间,避免内存溢出
@Configuration
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
cacheManager.setCaffeine(Caffeine.newBuilder()
.expireAfterWrite(30, TimeUnit.MINUTES)
.maximumSize(1000));
return cacheManager;
}
}
7.3 异步处理
将非关键路径的操作改为异步执行,如通知发送、日志记录等:
@Async
public CompletableFuture<Void> sendNotificationAsync(String userId, String message) {
// 发送通知逻辑
return CompletableFuture.runAsync(() -> {
// 异步执行的代码
});
}
8. 扩展开发:自定义组件与适配器实现
8.1 自定义条件策略
Warm-Flow允许你扩展自定义的条件判断策略:
public class ConditionStrategyCustom extends AbstractConditionStrategy {
@Override
public String getType() {
return "CUSTOM"; // 自定义条件类型
}
@Override
public boolean condition(FlowParams flowParams, String express, Object val) {
// 自定义条件判断逻辑
// express: 条件表达式
// val: 实际值
return customCheck(express, val);
}
private boolean customCheck(String express, Object val) {
// 实现自定义的条件检查逻辑
return true;
}
}
// 注册自定义条件策略
@Component
public class CustomConditionConfig {
@Autowired
private ConditionStrategyFactory conditionStrategyFactory;
@PostConstruct
public void init() {
conditionStrategyFactory.register(new ConditionStrategyCustom());
}
}
8.2 ORM适配器扩展
如果你需要使用Warm-Flow不直接支持的ORM框架,可以实现自定义的ORM适配器:
public class MyBatisFlexAdapter implements OrmAdapter {
@Autowired
private FlowDefinitionMapper flowDefinitionMapper;
@Override
public FlowDefinition selectByFlowKeyAndVersion(String flowKey, Integer version) {
return flowDefinitionMapper.selectOne(
Wrappers.<FlowDefinition>lambdaQuery()
.eq(FlowDefinition::getFlowKey, flowKey)
.eq(FlowDefinition::getVersion, version)
);
}
// 实现其他必要的方法...
}
9. 常见问题与解决方案
9.1 集成问题
Q: 启动项目时提示找不到FlowEngine bean?
A: 请检查是否在Spring Boot启动类上添加了@EnableWarmFlow注解,或者是否正确引入了starter依赖。
Q: 设计器无法访问?
A: 检查配置项warm.flow.designer.enabled是否设置为true,以及是否有拦截器阻止了访问。
9.2 运行时问题
Q: 流程启动后没有生成任务?
A: 可能是流程定义中没有正确设置任务节点的办理人,请检查流程定义的节点配置。
Q: 条件分支没有按预期执行?
A: 检查条件表达式是否正确,以及流程变量是否按预期传递。可以开启debug模式查看详细日志。
9.3 性能问题
Q: 流程实例较多时,查询待办任务变慢?
A: 请确保在任务表的assignee字段上建立了索引,并考虑使用缓存优化。
10. 总结与展望
Warm-Flow作为一款国产轻量级工作流引擎,以其简洁易用、功能全面、扩展性强的特点,为开发者提供了一个优秀的工作流解决方案。通过本文的介绍,相信你已经对Warm-Flow有了全面的了解,并能够开始在项目中实践应用。
随着企业数字化转型的深入,工作流引擎的应用场景将越来越广泛。Warm-Flow团队也将持续迭代优化,未来计划支持更多高级特性,如:
- AI辅助流程设计
- 低代码平台集成
- 更丰富的统计分析功能
如果你在使用过程中有任何问题或建议,欢迎加入Warm-Flow社区与我们交流。
附录:参考资源
- 官方文档:https://warm-flow.dromara.org/
- 源代码仓库:https://gitcode.com/dromara/warm-flow
- 演示地址:http://www.hhzai.top (admin/admin123)
- 测试案例:https://gitee.com/dromara/warm-flow-test
Kimi-K2.5Kimi K2.5 是一款开源的原生多模态智能体模型,它在 Kimi-K2-Base 的基础上,通过对约 15 万亿混合视觉和文本 tokens 进行持续预训练构建而成。该模型将视觉与语言理解、高级智能体能力、即时模式与思考模式,以及对话式与智能体范式无缝融合。Python00
GLM-4.7-FlashGLM-4.7-Flash 是一款 30B-A3B MoE 模型。作为 30B 级别中的佼佼者,GLM-4.7-Flash 为追求性能与效率平衡的轻量化部署提供了全新选择。Jinja00
VLOOKVLOOK™ 是优雅好用的 Typora/Markdown 主题包和增强插件。 VLOOK™ is an elegant and practical THEME PACKAGE × ENHANCEMENT PLUGIN for Typora/Markdown.Less00
PaddleOCR-VL-1.5PaddleOCR-VL-1.5 是 PaddleOCR-VL 的新一代进阶模型,在 OmniDocBench v1.5 上实现了 94.5% 的全新 state-of-the-art 准确率。 为了严格评估模型在真实物理畸变下的鲁棒性——包括扫描伪影、倾斜、扭曲、屏幕拍摄和光照变化——我们提出了 Real5-OmniDocBench 基准测试集。实验结果表明,该增强模型在新构建的基准测试集上达到了 SOTA 性能。此外,我们通过整合印章识别和文本检测识别(text spotting)任务扩展了模型的能力,同时保持 0.9B 的超紧凑 VLM 规模,具备高效率特性。Python00
KuiklyUI基于KMP技术的高性能、全平台开发框架,具备统一代码库、极致易用性和动态灵活性。 Provide a high-performance, full-platform development framework with unified codebase, ultimate ease of use, and dynamic flexibility. 注意:本仓库为Github仓库镜像,PR或Issue请移步至Github发起,感谢支持!Kotlin07
compass-metrics-modelMetrics model project for the OSS CompassPython00