灵动如画 —— 初识 Solon Graph Fluent API 编排

Solon Flow 在提供 json/ xml 编排之后。还提供了一套极为丝滑的流程图 Fluent API。它让流程定义回归到程序员最熟悉的工具------代码。

通过 Fluent API,你可以像写 Java Stream 一样,通过链式调用快速勾勒出业务流转图。

1、环境准备

首先,确保你的 Java 项目中已经引入了 solon-flow 依赖:

xml 复制代码
<dependency>
    <groupId>org.noear</groupId>
    <artifactId>solon-flow</artifactId>
</dependency>

2、核心概念:Graph 与 GraphSpec

在动手写代码前,需要理解两个关键概念:

  • Graph (图):流程的最终实体,包含所有节点和连线的运行逻辑。
  • GraphSpec (图规格/定义):它是构建图的"蓝图"。在 v3.8 之后,它是 Fluent API 操作的核心对象。

3、 实战:手动编排一个"订单处理流"

假设我们有一个简单的订单流程:开始 -> 检查库存 -> 支付 -> 结束。

  • 第一步:准备业务处理组件()

Solon-flow 的设计理念是 "逻辑与实现分离"。 我们先定义具体的业务动作:

java 复制代码
import org.noear.solon.annotation.Component;
import org.noear.solon.flow.FlowContext;
import org.noear.solon.flow.Node;
import org.noear.solon.flow.TaskComponent;

// 容器 Bean 的形式(此处以 Solon 为例)
@Component("checkStock")
public class CheckStockProcessor implements TaskComponent {
    @Override
    public void run(FlowContext ctx, Node node) throws Throwable {
        System.out.println("--- 正在检查库存... ---");
        ctx.put("stock_ok", true); // 在上下文中存入结果
    }
}

//-------------

// 普通 Java 类形式
import org.noear.solon.annotation.Component;
import org.noear.solon.flow.FlowContext;
import org.noear.solon.flow.Node;
import org.noear.solon.flow.TaskComponent;


public class PayProcessor implements TaskComponent {
    @Override
    public void run(FlowContext context, Node node) throws Throwable {
        System.out.println("--- 支付成功! ---");
    }
}
  • 第二步:使用 Fluent API 编排流程

下面是本文的核心代码。我们通过 Graph.create 启动编排:

java 复制代码
import org.noear.solon.flow.Graph;

public class FlowConfig {

    public Graph buildOrderFlow() {
        // 使用 Fluent API 构建
        return Graph.create("order_flow", "订单处理流程", spec -> {
            // 1. 定义开始节点并连接到下一个
            spec.addStart("n1").title("开始").linkAdd("n2");

            // 2. 定义业务节点,绑定对应的 Bean 标识
            spec.addActivity("n2")
                    .title("库存检查")
                    .task("@checkStock") // 关联上面定义的 Bean(从容器获取)
                    .linkAdd("n3");

            spec.addActivity("n3")
                    .title("支付")
                    .task(new PayProcessor()) //硬编码方式(不用经过容器)
                    .linkAdd("n4");

            // 3. 定义结束节点
            spec.addEnd("n4").title("结束");
        });
    }
}

4、关键 API 深度解析

  • spec.addStart(id) / addEnd(id):定义流程的边界。每一个图必须有且只有一个 Start 节点,可以有多个 End 节点。
  • spec.addActivity(id):这是最常用的节点,代表一个具体任务。
  • .task("@beanName"):这是核心联动点。@ 符号告诉 Solon 去容器中寻找对应的处理器。
  • .linkAdd(targetId):最简单的单向连线。它建立了一个从当前节点到目标节点的直接流转。

5、如何运行这个图?

有了 Graph 对象后,我们需要通过 FlowEngine 来触发它:

java 复制代码
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;
import org.noear.solon.flow.FlowContext;
import org.noear.solon.flow.FlowEngine;
import org.noear.solon.flow.Graph;

@Component
public class OrderService {
    @Inject
    FlowEngine flowEngine;

    public void processOrder() {
        // 1. 构建图(实际生产中通常会缓存此对象)
        Graph orderGraph = new FlowConfig().buildOrderFlow();

        // 2. 准备执行上下文(可以携带业务参数)
        FlowContext context = FlowContext.of("ORD-20231024");

        // 3. 执行流程
        flowEngine.eval(orderGraph, context);
    }
}

总结与预告

通过本文,你已经学会了如何不依赖任何配置文件,纯手工在内存中"画"出一个流程图。这种方式极大地提高了代码的可读性,并且让"流程定义"本身也成为了类型安全的代码。

但是,现实中的流程往往不是一条直线。 如果库存不足怎么办?如果金额巨大需要人工审批怎么办?

在后面的 《逻辑之魂 ------ 节点的"条件流转"与表达式》 中,我们将引入"分支判断",让你的 Graph 真正具备处理复杂业务的能力。

相关推荐
dmonstererer7 小时前
【k8s设置污点/容忍】
java·容器·kubernetes
super_lzb7 小时前
mybatis拦截器ParameterHandler详解
java·数据库·spring boot·spring·mybatis
程序之巅7 小时前
VS code 远程python代码debug
android·java·python
我是Superman丶8 小时前
【异常】Spring Ai Alibaba 流式输出卡住无响应的问题
java·后端·spring
墨雨晨曦888 小时前
Nacos
java
invicinble8 小时前
seata的认识与实际开发要做的事情
java
乌日尼乐8 小时前
【Java基础整理】Java多线程
java·后端
2501_941870568 小时前
从配置频繁变动到动态配置体系落地的互联网系统工程实践随笔与多语言语法思考
java·前端·python
她说..9 小时前
Spring 核心工具类 AopUtils 超详细全解
java·后端·spring·springboot·spring aop
TH_19 小时前
33、IDEA无法获取最新分支
java·ide·intellij-idea