Java 流程编排新范式 Solon Flow:一个引擎,七种节点,覆盖规则/任务/工作流/AI 编排全场景 当业务复杂度爆炸你的代码还能撑多久做过复杂业务的 Java 开发者大概都经历过这样的噩梦一个订单处理方法从最初的 50 行经过三轮需求迭代膨胀到 500 行。里面嵌套着六层 if-else夹杂着硬编码的分支逻辑改一处怕崩一片。新人来了看不懂老人走了不敢改。更糟糕的是产品经理隔三差五就跑过来说这个审批流程要加一个总监审批环节、满减规则从三档改成五档、大客户走特殊通道……每一次变更都是一次代码外科手术。流程编排就是为解决这个问题而生的。把散落在代码各处的业务逻辑抽象为一个个独立的节点然后用声明式的方式定义它们的执行顺序和分支条件。这样既解耦了代码又让业务规则一目了然更重要的是——规则的变更不再需要修改 Java 代码、走完整的发版流程。今天要介绍的是——Solon Flow。它不仅覆盖了 “规则编排” 和 “任务流水线”还原生支持 “AI Agent 编排”而且不绑定任何特定框架Spring Boot 项目一样能用。一、Solon Flow 是什么Solon Flow 是基于 Solon 框架 构建的通用流程编排引擎采用偏平式编排设计所有节点平铺在同一个层级通过 link连接线描述节点之间的流转关系。它不依赖树形嵌套、不依赖 EL 表达式而是用最直觉的图结构来表达业务流程。设计理念1. 偏平式编排Solon Flow 把所有节点平铺用 link 的when条件控制流向。这种风格更接近流程图的直觉表达也更容易被非开发角色理解。# 偏平式编排节点平铺link 描述连接关系 id: order_flow layout: - id: start type: start link: check_order - id: check_order type: activity task: checkOrderTask link: - nextId: vip_route when: amount 1000 - nextId: normal_route - id: ...2. 元数据无限扩展每个节点都可以附加任意meta属性。这意味着你可以在不修改引擎代码的前提下为节点注入角色信息、表单定义、超时策略、重试次数等业务元数据实现高度的定制化。比如审批流中你可以在 meta 里定义每个审批节点对应的角色role: tl和表单form: approval_form运行时由驱动器读取并执行对应的权限检查。这种设计让 YAML 文件不仅是执行编排的定义同时也是一份业务级的配置文档。3. 驱动可定制Solon Flow 引入了类似 JDBC 驱动的机制——引擎本身只定义执行骨架具体的任务调度、条件评估等行为通过driver驱动器接口注入。这意味着同一套编排定义换一个驱动器就能变成不同的执行范式。默认驱动器使用 Solon 的 IoC 容器来解析TaskComponent但你完全可以提供一个纯 Spring 驱动器让它通过 Spring 的ApplicationContext来获取 Bean。这种可插拔的驱动设计是 Solon Flow 实现框架无关的关键技术基础。4. 可中断可恢复这是 Solon Flow 最独特的能力之一。通过context.stop()中断流程用context.toJson()将执行快照序列化持久化之后通过FlowContext.fromJson()恢复上下文引擎会自动从中断节点继续执行。注意——不是从起点重新执行而是精确地从上次中断的节点继续。这个能力对审批流、长流程、AI Agent 的持久化至关重要。你可以把快照存到数据库、Redis、甚至消息队列中根据业务需要灵活选择持久化策略。二、七种节点类型全解析Solon Flow 定义了 7 种节点类型覆盖了流程编排中最常见的执行模式。节点类型标识说明典型场景开始节点start图的唯一入口无任务执行流程起点活动节点activity执行具体业务逻辑的默认节点计算任务、服务调用包容网关inclusive多选分支满足条件的都执行汇聚时等待所有已激活分支多条件触发排它网关exclusive单选分支按优先级选择唯一一条路径条件路由并行网关parallel全选分支所有连接都执行汇聚时等待全部完成并行计算循环网关loop遍历集合或区间每个元素执行一次子流程批量处理结束节点end图的终点流程结束下面逐个看 YAML 配置示例。start — 开始节点- id: s1 type: start title: 流程开始 link: n1start 节点是图的唯一入口不执行任务只负责触发后续节点。每个图有且只有一个 start 节点。从 v3.8.4 开始start 节点支持自由流出连接与 activity 类似可以连接多个下游节点。activity — 活动节点默认- id: n1 type: activity title: 数据校验 task: validateTask meta: role: admin link: n2activity 是最常用的节点类型执行具体的业务逻辑通过task绑定TaskComponent还可以通过meta携带任意扩展数据。exclusive — 排它网关单选- id: g1 type: exclusive title: 金额分级 link: - nextId: n2 title: 3天以下 - nextId: n3 title: 3天以上 when: day 3排它网关按连接声明的优先级依次评估when条件选择第一个满足条件的路径执行。没有when条件的连接视为默认路由兜底。inclusive — 包容网关多选- id: g1 type: inclusive title: 权益发放 link: - nextId: coupon_task when: orderAmount 100 - nextId: point_task when: orderAmount 50 - nextId: gift_task when: orderAmount 500包容网关会评估所有流出连接的条件所有满足条件的分支都会执行汇聚时等待所有已激活的分支完成。类似于多选多。parallel — 并行网关全选- id: p1 type: parallel #流出 title: 并行查询 link: - nextId: query_user - nextId: query_order - nextId: query_inventory # ... 三个任务各自完成后汇聚到 p2 - id: p2 type: parallel #流入网关汇聚 title: 汇聚结果 link: merge_result并行网关的流出连接全部执行多线程并行或单线程执行汇聚端等待所有流入连接到齐后才继续。适合同时调用多个独立服务的场景。loop — 循环网关遍历- id: loop1 type: loop #流出 title: 遍历订单项 meta: $for: order # 指定要遍历接收变量名 $in: orderList # 指定要遍历的集合变量名 link: process_item - id: process_item type: activity task: processItemTask - type: loop #流入网关汇聚循环网关会对集合中的每个元素执行一次子流程通过$for、$in元数据指定遍历的集合变量名。end — 结束节点- id: e1 type: end title: 流程结束end 节点标记流程的终点。一个图可以有多个 end 节点对应不同的结束路径但每个 end 节点不能有流出连接。流程执行到 end 节点时引擎会记录完成状态context.lastRecord().isEnd()返回true。三、五大实战场景掌握了七种节点类型后我们来看五个典型的实战场景从简单到复杂逐步深入。场景 A业务规则引擎 — 订单金额分级积分计算先看一个经典的需求根据订单金额计算积分规则经常变化不想每次改代码重新发版。传统 if-else 写法public int calculatePoints(Order order) { if (order.getAmount() 10000) { return (int)(order.getAmount() * 0.15); } else if (order.getAmount() 5000) { return (int)(order.getAmount() * 0.10); } else if (order.getAmount() 1000) { return (int)(order.getAmount() * 0.05); } else { return (int)(order.getAmount() * 0.01); } }每次规则变化都要改代码、测试、发版。现在用 Solon Flow 改造。YAML 编排定义id: points_calc nodes: - id: start type: start link: g1 - id: g1 type: exclusive title: 积分分级 link: - nextId: diamond when: amount 10000 - nextId: gold when: amount 5000 - nextId: silver when: amount 1000 - nextId: normal - id: diamond type: activity title: 钻石级积分 meta: rate: 0.15 task: ratePointsTask link: end - id: gold type: activity title: 黄金级积分 meta: rate: 0.10 task: ratePointsTask link: end - id: silver type: activity title: 白银级积分 meta: rate: 0.05 task: ratePointsTask link: end - id: normal type: activity title: 普通积分 meta: rate: 0.01 task: ratePointsTask link: end - id: end type: endJava 调用代码// 引擎初始化一行代码搞定 FlowEngine engine FlowEngine.newInstance(); Graph graph Graph.fromUri(points_calc.yml); // 执行 FlowContext context FlowContext.of(); context.put(amount, 6800); engine.eval(graph, context); int points context.getAs(points);核心 API 就三个FlowEngine.newInstance()创建引擎、Graph.fromUri()加载编排定义、engine.eval()执行。学习成本极低五分钟上手。TaskComponent 实现所有分级共用一个Component(ratePointsTask) public class RatePointsTask implements TaskComponent { Override public void run(FlowContext ctx, Node node) throws Throwable { double amount ctx.getAs(amount); double rate Double.parseDouble(node.getMeta(rate)); ctx.put(points, (int)(amount * rate)); } }注意看四个分级节点共享同一个ratePointsTask通过node.getMeta(rate)读取 YAML 中定义的rate元数据。这意味着新增一个分级只需要在 YAML 中加一个节点和对应的 rate 值Java 代码完全不用动。优势对比传统 if-else 方式新增分级要改 Java 代码、走测试流程、发版上线Solon Flow 方式只需修改 YAML 文件中的阈值和费率运维同学甚至可以在线上直接修改配置。当规则从四档变成六档、十档时收益会更加明显。场景 B任务编排 — 数据抓取流水线一个典型的 ETL 场景抓取数据 → 清洗 → 存储 → 通知。每个环节都是独立的组件用 activity 节点串联。YAML 定义id: etl_pipeline nodes: - id: start type: start link: fetch - id: fetch type: activity title: 数据抓取 task: fetchDataTask link: clean - id: clean type: activity title: 数据清洗 task: cleanDataTask link: store - id: store type: activity title: 数据存储 task: storeDataTask link: notify - id: notify type: activity title: 完成通知 task: notifyTask link: end - id: end type: endTaskComponent 实现Component(fetchDataTask) public class FetchDataTask implements TaskComponent { Override public void run(FlowContext ctx, Node node) throws Throwable { // 调用外部 API 抓取数据 ListRawData data apiClient.fetch(ctx.getAs(source)); ctx.put(rawData, data); } } Component(cleanDataTask) public class CleanDataTask implements TaskComponent { Override public void run(FlowContext ctx, Node node) throws Throwable { ListRawData raw ctx.getAs(rawData); ListCleanData cleaned raw.stream() .filter(d - d.isValid()) .map(this::transform) .collect(Collectors.toList()); ctx.put(cleanData, cleaned); } }流水线的每一步都是一个独立的TaskComponent通过FlowContext传递数据。这种设计带来了几个好处每个 TaskComponent 可以独立测试——不依赖 FlowEngine直接构造 FlowContext 传入即可单元测试组件复用——同一个 TaskComponent 可以在不同的图中被引用插入/删除步骤零侵入——如果需要在清洗和存储之间插入一个去重步骤只需要在 YAML 里加一个节点和一条 linkJava 代码完全不需要改动执行顺序可视化——YAML 文件本身就是一份可读的流程文档产品经理和测试同学都能看懂场景 C并行计算 — 多任务并行执行当流水线中存在多个互不依赖的任务时可以用 parallel 网关让它们并行执行显著缩短总耗时。YAML 定义id: parallel_query nodes: - id: start type: start link: fork - id: fork type: parallel title: 并行查询 link: - nextId: query_user - nextId: query_order - nextId: query_risk - id: query_user type: activity title: 查询用户信息 task: queryUserTask link: join - id: query_order type: activity title: 查询订单信息 task: queryOrderTask link: join - id: query_risk type: activity title: 风控评估 task: queryRiskTask link: join - id: join type: parallel title: 汇聚结果 link: aggregate - id: aggregate type: activity title: 汇总决策 task: aggregateTask link: end - id: end type: end三个查询任务并行执行join节点parallel 类型会等待三个分支全部完成后再流转到aggregate节点进行汇总。原来串行 3 秒的任务1s 0.8s 1.2s并行后总耗时取决于最慢的那个分支可能只需 1.2 秒。使用 parallel 网关需要注意几个要点parallel 网关必须成对使用——一个 fork分叉、一个 join汇聚join 端会等待所有流入连接到齐任何一个分支异常都会导致汇聚失败并行执行的线程策略由 driver 决定默认使用线程池并行执行各分支之间通过各自的FlowContext隔离互不干扰场景 D可中断与恢复的审批流审批流是流程编排的经典场景。一个订单需要经过主管和总监两级审批但审批人不是实时在线的流程需要在中途暂停等审批完成后再继续。YAML 定义id: order_approval nodes: - id: start type: start link: submit - id: submit type: activity title: 提交订单 task: submitTask link: tl_review - id: tl_review type: activity title: 主管审批 task: tlReviewTask link: vp_review - id: vp_review type: activity title: 总监审批 task: vpReviewTask link: end - id: end type: end审批 Task 的中断逻辑Component(tlReviewTask) public class TlReviewTask implements TaskComponent { Override public void run(FlowContext ctx, Node node) throws Throwable { ApprovalState state ctx.getAs(approvalState); if (!state.isTlApproved()) { // 主管尚未审批中断流程 System.out.println(等待主管审批...); ctx.stop(); // 关键停止执行 } else { System.out.println(主管已通过流转到总监审批。); } } }中断后的持久化与恢复FlowEngine engine FlowEngine.newInstance(); Graph graph Graph.fromUri(order_approval.yml); FlowContext context FlowContext.of(order-001); // 第一次执行提交后主管审批环节被中断 context.put(approvalState, new ApprovalState()); engine.eval(graph, context); // context.isStopped() true流程被暂停了 System.out.println(当前停在节点: context.lastNodeId()); // 输出: tl_review // 持久化到数据库 String snapshot context.toJson(); approvalRepository.saveSnapshot(order-001, snapshot); // ---- 几天后主管完成了审批 ---- // 从数据库恢复 String json approvalRepository.getSnapshot(order-001); FlowContext restored FlowContext.fromJson(json); restored.put(approvalState, new ApprovalState(true, false)); // 主管已批 // 引擎自动从 tl_review 节点继续执行 engine.eval(graph, restored);这就是 Solon Flow 的中断-恢复机制stop()→toJson()持久化 →fromJson()恢复 →eval()继续。整个过程中业务数据的完整性由快照保证引擎自动定位到中断节点。场景 EAI 智能体编排这是 Solon Flow最差异化的能力也是其他编排框架几乎没有覆盖的领域。Solon 的 AI 生态构建在 Flow 之上提供了三个层次的智能体能力插件智能体模式说明solon-ai-flowAiFlow 工作流模式偏软编排用 YAML 编排 AI 工作流solon-ai-agentReActAgent 自我反省模式单兵作战思考行动循环solon-ai-agentTeamAgent 团队协作模式多智能体系统分工协作ReActAgent思考-行动-观察的闭环ReActAgent 的核心是思考Thought→ 行动Action→ 观察Observation的推理循环。它底层就是一个由 Solon Flow 构建的计算图Start → [Plan(可选)] → [Reason(决策)] ↔ [Action(执行工具)] → End// 构建一个技术支持专家 ReActAgent techAgent ReActAgent.of(chatModel) .name(tech_support) .role(技术支持专家) .instruction(负责处理客户技术问题可查询数据库和排查日志) .defaultToolAdd(dbQueryTool) // 注入数据库查询工具 .defaultToolAdd(logSearchTool) // 注入日志搜索工具 .maxSteps(12) // 最多推理 12 步 .build(); // 执行任务 AssistantMessage result techAgent .prompt(查询最近1小时订单号为 ORD-20260517-001 的错误日志) .call();TeamAgent多智能体团队协作当任务需要多个不同角色的专家协作时TeamAgent 登场。它本身不执行任务而是作为总指挥通过TeamProtocol协作协议将多个 Agent 编织成协同作战单元。TeamAgent tripAgent TeamAgent.of(chatModel) .name(trip_manager) .role(旅行规划团队) .agentAdd(ReActAgent.of(chatModel) .name(searcher) .role(天气搜索员) .instruction(负责提供实时气候数据) .defaultToolAdd(weatherTool) .build()) .agentAdd(ReActAgent.of(chatModel) .name(planner) .role(行程规划师) .instruction(根据天气数据规划行程) .build()) .protocol(TeamProtocols.SEQUENTIAL) // 顺序协作协议 .build(); // 执行团队任务 AssistantMessage result tripAgent .prompt(帮我规划上海周末行程) .call();AiFlow工作流智能体YAML 编排 AI如果你更喜欢声明式地编排 AI 工作流solon-ai-flow提供了类似 Dify 的工作流模式但它是纯开发框架而非低代码平台dependency groupIdorg.noear/groupId artifactIdsolon-ai-flow/artifactId /dependencyAiFlow 内置了多种预置组件输入组件接收用户消息、模型组件调用 LLM、RAG 组件检索增强生成、输出组件返回结果。你可以用 YAML 定义这些组件之间的流转关系像搭积木一样拼装出复杂的 AI 工作流。而且由于底层就是 Solon Flow你可以随时用自定义的TaskComponent替换或扩展任何预置组件——这是它区别于 Dify 等封闭式低代码平台的核心优势。关键洞察Solon Flow 不是为了 AI 而生但它的图驱动执行模型天然适合 AI Agent 的编排需求。ReActAgent 的推理循环Reason ↔ Action、TeamAgent 的多角色协作路由决策 专家分发底层都是 Solon Flow 的 Graph 在驱动。这意味着——你在 Flow 上积累的编排经验、调试手段和可视化工具可以无缝复用到 AI 场景。当你的业务系统未来需要引入 AI 能力时不需要再学习一套全新的编排框架。另一个值得注意的点TeamAgent 支持持久化与恢复。你可以将多智能体协作的中间状态序列化为 JSON 快照存入数据库系统重启后从中断点继续执行。这对于耗时较长的 AI 任务如多轮分析、大规模报告生成非常关键。四、框架无关六种框架都能用一个常见的疑虑Solon Flow 是不是必须用 Solon 框架答案是不需要。Solon Flow 可以作为纯 JAR 包引入不需要 Solon 容器。官方提供了完整的嵌入式示例覆盖主流 Java 框架嵌入框架示例模块Spring Boot 2solon-flow-in-springboot2Spring Boot 3solon-flow-in-springboot3Spring Boot 4solon-flow-in-springboot4Spring MVCsolon-flow-in-springmvcjFinalsolon-flow-in-jfinalVert.Xsolon-flow-in-vertxQuarkussolon-flow-in-quarkusMicronautsolon-flow-in-micronaut示例仓库地址GitHub: https://github.com/solonlab/solon-flow-embedded-examplesGitee: https://gitee.com/solonlab/solon-flow-embedded-examplesMaven 依赖就一个 JARdependency groupIdorg.noear/groupId artifactIdsolon-flow/artifactId version3.10.7/version /dependency在 Spring Boot 项目中只需要引入这个依赖然后通过 Java API 方式使用 FlowEngine不需要任何 Solon 相关的配置。核心 API 非常简洁// 1. 创建引擎 FlowEngine engine FlowEngine.newInstance(); // 2. 从 classpath 加载 YAML Graph graph Graph.fromUri(my_flow.yml); // 3. 构建上下文并执行 FlowContext context FlowContext.of(); context.put(key, value); engine.eval(graph, context); // 4. 读取结果 Object result context.getAs(result);这就是全部的 API 了。没有 XML 配置没有 Spring Boot Starter 要引入没有自动装配要理解。FlowEngine是无状态的线程安全可以全局复用一个实例。Graph加载后也是不可变的可以缓存。只有FlowContext是每次执行需要新建的。