一、为什么需要流程编排?
做后台开发的同学一定遇到过这类需求:
- 请假审批:员工提交 -> 主管审批 -> 部门经理审批 -> 副总审批,但不同天数的审批链路还不一样
- 合同审批:金额超过 10 万需要额外部门会签,超过 50 万需要财务参与
- 数据抓取:多线程并行爬取多个数据源,再汇总处理
这类需求本质上都是一个 有向图 的流转问题。如果全靠 if-else 硬编码,代码很快就会变成面条式意大利粉。
Solon Flow 是 Solon 生态中的通用流程编排框架,它的核心思路是:用 YAML(或 Java Fluent API)描述流转逻辑,用引擎驱动执行。不需要重依赖、不需要外部数据库、不需要部署服务,一个 jar 包就能跑。
今天这篇文章,我们用最经典的"请假审批流"作为实战案例,从零到一跑通 Solon Flow 的核心能力。
二、5 分钟跑起来:Hello World
2.1 添加依赖
在 pom.xml 中添加:
xml
<dependency>
<groupId>org.noear</groupId>
<artifactId>solon-flow</artifactId>
</dependency>
不需要额外数据库、不需要消息中间件,一个依赖搞定。
2.2 创建流程定义文件
在 resources/flow/ 目录下创建 demo1.yml:
yaml
id: "demo1"
layout:
- { id: "s", type: "start", link: "n1" }
- { id: "n1", type: "activity", task: 'System.out.println("hello world!");', link: "e" }
- { id: "e", type: "end" }
这是一个最简单的三节点流程:开始 -> 执行打印 -> 结束。
2.3 执行
两种方式,任选其一:
方式一:原生 Java 模式(不需要启动 Solon 容器)
java
import org.noear.solon.flow.FlowEngine;
public class Demo {
public static void main(String[] args) {
FlowEngine engine = FlowEngine.newInstance();
engine.load("classpath:flow/*");
engine.eval("demo1");
// 控制台输出:hello world!
}
}
方式二:Solon 容器注解模式
先在应用配置中声明流程文件位置:
yaml
# application.yml
solon.flow:
- "classpath:flow/*.yml"
然后在组件中注入引擎直接使用:
java
@Component
public class DemoCom implements LifecycleBean {
@Inject
private FlowEngine flowEngine;
@Override
public void start() throws Throwable {
flowEngine.eval("demo1");
}
}
运行后控制台输出:hello world!。5 分钟,一个流程就跑通了。
三、核心概念速览:7 种节点 + 引擎 + 上下文
在进入实战之前,先过一遍 Solon Flow 的核心概念。这些概念非常精简,但足够覆盖绝大多数编排场景。
3.1 七种节点类型
Solon Flow 的图由 7 种节点 构成:
| 节点类型 | 说明 | 执行任务 | 连接条件 | 多线程 | 可流入 | 可流出 |
|---|---|---|---|---|---|---|
| start | 开始节点 | - | - | - | 0 | 1 |
| activity | 活动节点(缺省类型) | 支持 | - | - | 1...n | 1...n |
| exclusive | 排他网关(单选) | 支持 | 支持 | - | 1...n | 1...n |
| inclusive | 包容网关(多选) | 支持 | 支持 | - | 1...n | 1...n |
| parallel | 并行网关(全选) | 支持 | - | 支持 | 1...n | 1...n |
| loop | 循环网关 | 支持 | - | - | 1 | 1 |
| end | 结束节点 | - | - | - | 1...n | 0 |
几个关键点:
- start 和 end 每个图必须有且仅有一个
- exclusive(排他网关):相当于"单选",只有一条满足条件的连接会流出,没有匹配的用默认(无条件)连接
- inclusive(包容网关):相当于"多选",所有满足条件的连接都会流出,需要成对使用实现汇聚
- parallel(并行网关):相当于"全选",所有连接都会流出,内部使用多线程执行,需要成对使用实现汇聚
- loop (循环网关):遍历集合并循环流出,通过
$for和$in元数据指定变量
3.2 流程引擎(FlowEngine)
FlowEngine 是执行流程的核心入口,主要负责:
- 加载和解析流程定义(支持 YAML、JSON、Java 硬编码)
- 驱动流程执行
- 管理拦截器链
java
FlowEngine engine = FlowEngine.newInstance();
engine.load("classpath:flow/*.yml"); // 加载
engine.eval("demo1"); // 执行(按 id 匹配)
engine.eval("demo1", context); // 执行(带上下文)
engine.eval("demo1", 1, context); // 执行(深度控制,单步调试)
3.3 上下文(FlowContext)
FlowContext 是流程执行的核心现场,承载了业务数据、控制状态和执行轨迹:
java
// 创建
FlowContext context = FlowContext.of();
FlowContext context = FlowContext.of("instance-001");
// 传递业务参数
context.put("day", 5);
context.put("applicant", "张三");
// 获取参数
int day = context.getAs("day");
// 控制流程
context.stop(); // 停止(可用于中断恢复)
context.interrupt(); // 中断当前分支
// 序列化与恢复
String snapshot = context.toJson();
FlowContext restored = FlowContext.fromJson(snapshot);
// 执行轨迹
context.lastNodeId(); // 最后执行的节点 ID
context.trace(); // 完整执行轨迹
概念不多,但覆盖了编排、执行、控制、恢复四大核心能力。下面进入实战。
四、实战一:50 行 YAML 实现请假审批流(条件分支 exclusive)
4.1 业务规则
一个请假审批的流转规则如下:
员工发起请假
-> 主管审批
-> 天数 < 3天:直接结束(主管批了就行)
-> 天数 >= 3天:部门经理审批
-> 天数 < 7天:结束
-> 天数 >= 7天:副总审批 -> 结束
这是一个典型的 条件分支 场景,用 exclusive(排他网关)来实现。
4.2 流程定义
创建 resources/flow/leave-approval.yml:
yaml
id: "leave-approval"
title: "请假审批"
layout:
- { id: "s", type: "start", title: "发起人", meta: { role: "employee" }, link: "n1" }
- { id: "n1", type: "activity", title: "主管审批", task: "@tl_approve", link: "g1" }
- { id: "g1", type: "exclusive", title: "天数判断", link: [
{ nextId: "e", title: "3天以下" },
{ nextId: "n2", title: "3天以上", when: "day>=3" }
]}
- { id: "n2", type: "activity", title: "部门经理审批", task: "@dm_approve", link: "g2" }
- { id: "g2", type: "exclusive", title: "天数判断", link: [
{ nextId: "e", title: "7天以下" },
{ nextId: "n3", title: "7天以上", when: "day>=7" }
]}
- { id: "n3", type: "activity", title: "副总审批", task: "@vp_approve", link: "e" }
- { id: "e", type: "end" }
一共 8 个节点(含 start 和 end),YAML 共 50 行以内。
解释几个关键点:
task: "@tl_approve":以@开头的是任务组件引用,对应 Java 中注册的TaskComponentwhen: "day>=3":连接条件表达式,引擎通过表达式引擎(SnEL)求值,day从上下文中获取- 排他网关
g1:如果day>=3满足,走n2;否则走默认连接e(没有 when 的连接就是默认) meta: { role: "employee" }:元数据,可以在拦截器或任务中读取,用于权限判断等
4.3 任务组件实现
每个 task 中的 @xxx 引用,对应一个 Java 组件:
java
import org.noear.solon.flow.core.TaskComponent;
import org.noear.solon.flow.core.FlowContext;
import org.noear.solon.flow.core.Node;
// 主管审批
@Component("tl_approve")
public class TeamLeaderApprove implements TaskComponent {
@Override
public void run(FlowContext context, Node node) throws Throwable {
String applicant = context.getAs("applicant");
int day = context.getAs("day");
System.out.println("主管审批通过:申请人=" + applicant + ", 天数=" + day);
context.put("tl_approved", true);
}
}
// 部门经理审批
@Component("dm_approve")
public class DeptManagerApprove implements TaskComponent {
@Override
public void run(FlowContext context, Node node) throws Throwable {
String applicant = context.getAs("applicant");
System.out.println("部门经理审批通过:申请人=" + applicant);
context.put("dm_approved", true);
}
}
// 副总审批
@Component("vp_approve")
public class VPApprove implements TaskComponent {
@Override
public void run(FlowContext context, Node node) throws Throwable {
String applicant = context.getAs("applicant");
System.out.println("副总审批通过:申请人=" + applicant);
context.put("vp_approved", true);
}
}
4.4 测试运行
java
public class LeaveApprovalTest {
public static void main(String[] args) {
FlowEngine engine = FlowEngine.newInstance();
engine.load("classpath:flow/leave-approval.yml");
// 场景1:请假2天 -> 主管审批 -> 结束
FlowContext ctx1 = FlowContext.of()
.put("applicant", "张三")
.put("day", 2);
engine.eval("leave-approval", ctx1);
// 输出:主管审批通过:申请人=张三, 天数=2
// 场景2:请假5天 -> 主管 -> 部门经理 -> 结束
FlowContext ctx2 = FlowContext.of()
.put("applicant", "李四")
.put("day", 5);
engine.eval("leave-approval", ctx2);
// 输出:主管审批通过... 部门经理审批通过...
// 场景3:请假10天 -> 主管 -> 部门经理 -> 副总 -> 结束
FlowContext ctx3 = FlowContext.of()
.put("applicant", "王五")
.put("day", 10);
engine.eval("leave-approval", ctx3);
// 输出:主管审批通过... 部门经理审批通过... 副总审批通过...
}
}
这就是完整的请假审批流。50 行 YAML + 几个任务组件,流转逻辑一目了然。
五、实战二:并行网关 --- 同时发送短信和邮件通知
审批通过后,需要同时给申请人和 HR 发送短信通知和邮件通知。这是一个典型的 并行执行 场景,用 parallel(并行网关)来实现。
yaml
id: "notify-flow"
title: "审批通知"
layout:
- { id: "s", type: "start", link: "n1" }
- { id: "n1", type: "activity", title: "审批完成", task: "@after_approve", link: "g1" }
- { id: "g1", type: "parallel", title: "并行发送", link: ["n2", "n3"] }
- { id: "n2", type: "activity", title: "发送短信", task: "@send_sms", link: "g2" }
- { id: "n3", type: "activity", title: "发送邮件", task: "@send_email", link: "g2" }
- { id: "g2", type: "parallel", title: "汇聚结果", link: "e" }
- { id: "e", type: "end" }
关键说明:
g1是并行网关的 分叉端:所有流出连接都会同时执行(多线程)g2是并行网关的 汇聚端:等待所有流入连接到齐后,才继续往后流转- parallel 必须成对使用(分叉 + 汇聚)
任务组件:
java
@Component("send_sms")
public class SendSms implements TaskComponent {
@Override
public void run(FlowContext context, Node node) throws Throwable {
String applicant = context.getAs("applicant");
System.out.println("[短信] 通知 " + applicant + ":您的请假申请已审批通过");
}
}
@Component("send_email")
public class SendEmail implements TaskComponent {
@Override
public void run(FlowContext context, Node node) throws Throwable {
String applicant = context.getAs("applicant");
System.out.println("[邮件] 通知 " + applicant + ":您的请假申请已审批通过");
}
}
运行后,短信和邮件两个任务会 并行执行 (parallel 节点内部使用多线程),执行完毕后在 g2 汇聚,然后继续往后。
六、实战三:中断与恢复 --- 审批到一半要等领导出差回来
实际业务中,审批往往不是一次完成的。比如副总出差了,流程要暂停,等副总回来再继续。这就是 Solon Flow 的 中断与恢复 能力。
6.1 核心机制
- 在任务组件中调用
context.stop(),流程会停在当前节点 - 通过
context.toJson()将整个上下文序列化为 JSON 快照 - 需要恢复时,通过
FlowContext.fromJson()还原上下文 - 再次调用
engine.eval(),引擎会 自动从上次停止的节点继续执行
6.2 修改副总审批组件,加入中断逻辑
java
@Component("vp_approve")
public class VPApprove implements TaskComponent {
@Override
public void run(FlowContext context, Node node) throws Throwable {
String applicant = context.getAs("applicant");
boolean vpAvailable = context.getAs("vpAvailable"); // 副总是否在岗
if (!vpAvailable) {
System.out.println("副总出差中,流程暂停等待。申请人=" + applicant);
context.stop(); // 中断流程
return;
}
System.out.println("副总审批通过:申请人=" + applicant);
context.put("vp_approved", true);
}
}
6.3 执行与恢复
java
public class InterruptResumeTest {
public static void main(String[] args) {
FlowEngine engine = FlowEngine.newInstance();
engine.load("classpath:flow/leave-approval.yml");
// ===== 第一阶段:提交请假,副总出差,流程暂停 =====
FlowContext context = FlowContext.of("leave-001")
.put("applicant", "王五")
.put("day", 10)
.put("vpAvailable", false); // 副总不在
engine.eval("leave-approval", context);
// 输出:主管审批通过... 部门经理审批通过... 副总出差中,流程暂停等待
System.out.println("流程是否已停止: " + context.isStopped()); // true
System.out.println("最后执行节点: " + context.lastNodeId()); // n3
// 持久化快照到数据库(实际项目中)
String snapshot = context.toJson();
// db.save("leave-001", snapshot);
// ===== 第二阶段:副总回来了,恢复流程 =====
// 从数据库加载快照
// String snapshot = db.load("leave-001");
FlowContext restored = FlowContext.fromJson(snapshot);
restored.put("vpAvailable", true); // 更新状态:副总回来了
engine.eval("leave-approval", restored);
// 输出:副总审批通过:申请人=王五
}
}
这个能力非常强大。上下文的序列化和恢复是 快照级别 的,意味着:
- 可以跨线程恢复(异步回调场景)
- 可以跨时间恢复(长流程场景)
- 可以跨服务器恢复(分布式场景,配合数据库持久化快照)
非常适合审批流、AI 对话流等长流程场景。
七、实战四:循环遍历 --- 批量审批
假设部门经理需要一次性审批团队所有待处理的请假单,可以用 loop(循环网关) 实现:
yaml
id: "batch-approve"
title: "批量审批"
layout:
- { id: "s", type: "start", link: "g1" }
- { id: "g1", type: "loop", meta: { "$for": "item", "$in": "pendingList" }, link: "n1" }
- { id: "n1", type: "activity", title: "逐条审批", task: "@batch_item_approve", link: "g2" }
- { id: "g2", type: "loop", link: "e" }
- { id: "e", type: "end" }
关键说明:
- 第一个
loop节点g1是循环的 流出端 :通过$in从上下文中获取集合pendingList,用$for声明循环变量名item - 循环每取出一个元素,推入上下文变量
item,后续节点可直接使用 - 第二个
loop节点g2是循环的 汇聚端:等待遍历结束后才往后流转 - loop 必须成对使用
任务组件:
java
@Component("batch_item_approve")
public class BatchItemApprove implements TaskComponent {
@Override
public void run(FlowContext context, Node node) throws Throwable {
// 每次循环,item 变量自动推入上下文
Map<String, Object> item = context.getAs("item");
System.out.println("批量审批处理:" + item.get("applicant") + " - " + item.get("day") + "天");
}
}
执行:
java
FlowContext context = FlowContext.of()
.put("pendingList", Arrays.asList(
Map.of("applicant", "张三", "day", 1),
Map.of("applicant", "李四", "day", 4),
Map.of("applicant", "王五", "day", 8)
));
engine.eval("batch-approve", context);
// 输出:
// 批量审批处理:张三 - 1天
// 批量审批处理:李四 - 4天
// 批量审批处理:王五 - 8天
八、实战五:Graph 编码模式 --- 用 Java Fluent API 定义流程
除了 YAML,Solon Flow 还支持用纯 Java 代码定义流程。这在需要动态构建流程、或者流程需要根据参数动态调整的场景下非常有用。
java
import org.noear.solon.flow.core.Graph;
Graph graph = Graph.create("leave", spec -> {
spec.addStart("s").title("发起人").linkAdd("n1");
spec.addActivity("n1").title("主管审批").task("@tl_approve").linkAdd("g1");
spec.addExclusive("g1")
.linkAdd("e", l -> l.title("3天以下"))
.linkAdd("n2", l -> l.title("3天以上").when("day>=3"));
spec.addActivity("n2").title("部门经理审批").task("@dm_approve").linkAdd("g2");
spec.addExclusive("g2")
.linkAdd("e", l -> l.title("7天以下"))
.linkAdd("n3", l -> l.title("7天以上").when("day>=7"));
spec.addActivity("n3").title("副总审批").task("@vp_approve").linkAdd("e");
spec.addEnd("e");
});
// 直接执行
FlowEngine engine = FlowEngine.newInstance();
engine.eval(graph);
Fluent API 的方法名与 YAML 中的节点类型完全对应:
spec.addStart(id)/spec.addEnd(id)/spec.addActivity(id)/spec.addExclusive(id)....title()设置标题.task()设置任务.linkAdd(nextId)添加流出连接(无参 lambda 可设置连接标题和条件).when()设置连接条件表达式
此外,Graph 还支持复制和修改已有图:
java
// 复制并修改为新图
Graph graphNew = Graph.copy(graph, spec -> {
spec.removeNode("n3"); // 移除副总审批节点
spec.getNode("n2").linkRemove("n3").linkAdd("e"); // n2 直接连到 end
});
这种能力非常适合做 流程模板:先定义基础流程,再根据租户/业务线动态裁剪。
两种模式也可以互相转换:
java
// Graph -> YAML(反向序列化)
String yaml = graph.toYaml();
// Graph -> JSON
String json = graph.toJson();
// Graph -> PlantUML 状态图文本(v3.9.5+)
String plantuml = graph.toPlantuml();
九、高级能力:拦截器、事件总线、单步调试
9.1 拦截器(AOP 能力)
Solon Flow 提供了 FlowInterceptor 拦截器接口,可以在不修改流程定义和任务组件的前提下,对流程执行进行切面增强。
常见的使用场景:
| 场景 | 实现方式 |
|---|---|
| 性能监控 | doIntercept 中统计总耗时 |
| 执行审计 | onNodeStart 记录节点 ID 和上下文参数 |
| 安全校验 | doIntercept 中校验必要 Token |
| 参数补全 | 流程开始前向上下文注入全局配置 |
java
@Component
public class FlowAuditInterceptor implements FlowInterceptor {
static Logger log = LoggerFactory.getLogger(FlowAuditInterceptor.class);
@Override
public void doIntercept(FlowInvocation inv) throws Throwable {
long start = System.currentTimeMillis();
try {
inv.invoke(); // 执行流程
} catch (Throwable ex) {
log.error("流程执行异常: " + inv.getStartNode().getGraph().getId(), ex);
throw ex;
} finally {
long elapsed = System.currentTimeMillis() - start;
log.info("流程 {} 执行耗时: {}ms", inv.getStartNode().getGraph().getId(), elapsed);
}
}
@Override
public void onNodeStart(FlowContext context, Node node) {
log.info("节点开始: id={}, title={}", node.getId(), node.getTitle());
}
@Override
public void onNodeEnd(FlowContext context, Node node) {
log.info("节点完成: id={}, title={}", node.getId(), node.getTitle());
}
}
拦截器可以通过 Solon 容器自动注册(@Component),也可以手动注册:
java
engine.addInterceptor(new FlowAuditInterceptor());
9.2 事件总线(解耦利器)
Solon Flow 内置了基于 DamiBus 的事件总线,支持在流程执行中进行 上下文级别(实例级别) 的事件通信。
三种模式:
| 模式 | 方法 | 说明 |
|---|---|---|
| 发送 | send |
异步/同步广播,不要求答复 |
| 请求 | call |
发送并等待答复(类似 RPC) |
| 流 | stream |
发送并持续接收数据流 |
在流程中触发事件:
java
@Component("notify_task")
public class NotifyTask implements TaskComponent {
@Override
public void run(FlowContext context, Node node) throws Throwable {
// 发送事件(广播)
context.eventBus().send("leave.approved", context.getAs("applicant"));
}
}
在外部订阅事件:
java
FlowContext context = FlowContext.of();
context.eventBus().<String>listen("leave.approved", event -> {
System.out.println("收到审批通过通知: " + event.getPayload());
// 在这里处理:发企微通知、更新统计报表、推送消息队列等
});
engine.eval("leave-approval", context);
通过事件总线,流程定义只管"发信号",具体的业务处理(发通知、写日志、更新缓存)由外部监听器处理,实现了极度解耦。
9.3 单步前进(调试模式)
Solon Flow 支持深度控制,可以逐步执行流程中的每一个节点,类似调试器的单步执行:
java
FlowEngine engine = FlowEngine.newInstance();
engine.load("classpath:flow/leave-approval.yml");
FlowContext context = FlowContext.of()
.put("applicant", "张三")
.put("day", 2);
// 每次执行一步(深度=1)
engine.eval("leave-approval", 1, context);
System.out.println("当前节点: " + context.lastRecord().getTitle()); // 发起人
engine.eval("leave-approval", 1, context);
System.out.println("当前节点: " + context.lastRecord().getTitle()); // 主管审批
engine.eval("leave-approval", 1, context);
System.out.println("当前节点: " + context.lastRecord().getTitle()); // 天数判断
这个能力非常适合:
- 流程调试:开发阶段逐步排查问题
- 流程演示:向产品/业务逐步展示流转过程
- 交互式流程:每个节点执行后等待用户确认再继续
十、可视化设计器
对于不熟悉 YAML 的业务人员,Solon Flow 提供了 可视化设计器,可以通过拖拽的方式设计流程图,然后导出为 YAML/JSON。
设计器特点:
- 拖拽式节点编排,所见即所得
- 支持 7 种节点类型的可视化配置
- 可设置节点属性(标题、任务、条件、元数据等)
- 导出为 YAML/JSON/Map 格式,与代码模式无缝衔接
有了设计器,流程定义可以由业务人员直接参与维护,开发人员只需要关注任务组件的实现,实现真正的职责分离。
十一、包容网关补充 --- 条件会签场景
除了排他网关(单选)和并行网关(全选),还有一种 包容网关(inclusive),相当于"多选"------满足条件的连接都会流出。
以合同审批为例,金额不同需要不同部门会签:
yaml
id: "contract-approval"
title: "合同审批(条件会签)"
layout:
- { id: "s", type: "start", title: "发起人", meta: { role: "employee" }, link: "n1" }
- { id: "n1", type: "activity", title: "主管批", meta: { role: "tl" }, link: "g1" }
- { id: "g1", type: "inclusive", title: "会签", link: [
{ nextId: "n2", title: "10万以上", when: "amount>=100000" },
{ nextId: "n3", title: "50万以上", when: "amount>=500000" },
{ nextId: "n4", title: "90万以上", when: "amount>=900000" }
]}
- { id: "n2", type: "activity", title: "本部门经理批", task: "@dm_approve", link: "g2" }
- { id: "n3", type: "activity", title: "生产部经理批", task: "@prod_approve", link: "g2" }
- { id: "n4", type: "activity", title: "财务部经理批", task: "@fin_approve", link: "g2" }
- { id: "g2", type: "inclusive", link: "e" }
- { id: "e", type: "end" }
如果合同金额 80 万,则 g1 会同时流出 n2(10万以上)和 n3(50万以上),两个部门并行会签。g2 作为汇聚端,等待所有满足条件的流入到齐后才继续。
十二、总结与进阶
12.1 本文覆盖的核心能力
| 能力 | 对应特性 | 实战章节 |
|---|---|---|
| 条件分支 | exclusive 排他网关 | 实战一:请假审批 |
| 并行执行 | parallel 并行网关 | 实战二:并行通知 |
| 中断恢复 | context.stop() + toJson/fromJson | 实战三:中断恢复 |
| 循环遍历 | loop 循环节点 + f o r / for/ for/in | 实战四:批量审批 |
| Fluent API | Graph.create() 硬编码 | 实战五:Graph 编码 |
| 条件会签 | inclusive 包容网关 | 十一章:合同审批 |
| AOP 扩展 | FlowInterceptor 拦截器 | 高级能力 |
| 事件解耦 | DamiBus 事件总线 | 高级能力 |
| 单步调试 | eval(id, depth, context) | 高级能力 |
| 可视化设计 | 可视化设计器 | 第十章 |
12.2 Solon Flow 的适用场景
- 无状态流:计算编排、规则决策、数据抓取、AI Agent 工具调用链
- 有状态流:审批流、长流程、需要中断恢复的业务场景
- 混合场景:审批流 + 自动化任务编排的混合流程
12.3 进阶方向
如果你已经在项目中使用 Solon Flow,还可以关注以下进阶主题:
- solon-flow-workflow:在 solon-flow 基础上封装了工作流服务,提供任务认领(claimTask)、任务查找(findTask)、状态控制(StateController)、状态持久化(StateRepository)等开箱即用的工作流能力
- 引擎驱动定制 :通过自定义
FlowDriver实现不同的执行策略 - 元数据扩展 :通过
meta字段实现节点级别的自定义扩展(权限、超时、重试等) - Solon AI Flow:将 Solon Flow 与 AI 能力结合,实现 ReAct Agent、AI 工具链等场景
- PlantUML 导出 :通过
graph.toPlantuml()生成状态图文档,方便技术评审
12.4 项目信息
- 官网 :https://solon.noear.org
- Solon Flow 文档 :https://solon.noear.org/article/learn-solon-flow
- 源码仓库 :https://gitee.com/opensolon/solon
- 开源协议:Apache 2.0
- Java 兼容:Java 8 ~ Java 25
- Gitee GVP 项目
写在最后:流程编排的本质是"把流转逻辑从业务代码中抽离出来"。Solon Flow 用最轻量的方式做到了这一点------一个依赖、一个 YAML 文件、几行 Java 代码,就能跑起一个完整的审批流。如果你正在寻找一个轻量、灵活、不绑定外部服务的流程编排方案,值得试试。