用 Solon Flow 的 YAML DSL 撬动请假审批流——从有向图到可运行代码

2026-05-19 15 预计阅读时间:1 分钟
来源:oschina.net AI 摘要 原文链接

免责声明:本文为 AI 摘要整理,建议结合原文阅读。摘要可能省略上下文、版本差异或边界条件,不作为官方说明。

预计阅读时间:9 分钟

后台开发里有一类需求反复出现:审批链路随条件变长变短、多分支并行再汇合、超阈值触发额外环节。硬编码 if-else 嵌套三层就失控,用状态机又嫌重。Solon Flow 给了一条中间路线——用 YAML 描述有向图,引擎自动驱动节点流转,50 行就能跑起一条完整的请假审批流。

审批流的本质是有向图

先看几个典型场景:

  • 请假审批:1 天以内主管拍板,3 天以内加部门经理,超过 3 天还得副总签字——链路随天数动态拉长。
  • 合同审批:金额超 10 万触发会签,超 50 万财务必须介入——阈值决定分支。
  • 数据抓取:多线程并行爬多个源,全部完成后再汇总——并行再汇合。

这些需求的核心结构是一样的:节点 + 有向边 + 条件分支。硬写 Java 代码,每个分支一个 if,每个汇合一个计数器,代码量膨胀且难以复用。流程编排框架的价值在于:你只描述"图怎么画",引擎负责"节点怎么走"。

Solon Flow 的 YAML DSL

Solon Flow 是 Solon 框架的流程编排组件,核心思路是 YAML 定义流程图,Java 负责节点逻辑。一个流程定义文件大致结构如下:

flow:
  id: leave_approval
  nodes:
    - id: submit          # 员工提交
    - id: manager_review  # 主管审批
    - id: dept_review     # 部门经理审批
    - id: vp_review       # 副总审批
    - id: end             # 流程结束
  chains:
    - from: submit
      to: manager_review
    - from: manager_review
      to: dept_review
      when: days > 1       # 超过1天才走部门经理
    - from: manager_review
      to: end
      when: days <= 1      # 1天以内直接结束
    - from: dept_review
      to: vp_review
      when: days > 3       # 超过3天走副总
    - from: dept_review
      to: end
      when: days <= 3      # 3天以内直接结束
    - from: vp_review
      to: end

这段 YAML 做了几件事:

  1. 声明节点——每个审批环节是一个 node,id 是唯一标识。
  2. 声明边和条件——chains 定义从哪个节点到哪个节点,when 是路由条件,引擎根据上下文变量自动选择分支。
  3. 天然支持多分支——同一个 from 可以有多个 to,条件互斥时就是排他分支,条件不互斥时就是并行分支。

上面的 YAML 加上注释和空行约 50 行,已经覆盖了"不同天数走不同链路"的核心逻辑。

Java 端接入:节点逻辑与流程启动

YAML 只描述图,节点里干什么还得写 Java。Solon Flow 的节点组件用 @NodeComponent 注解声明:

// 主管审批节点
@NodeComponent("manager_review")
public class ManagerReviewNode implements NodeComponent {
    @Override
    public void execute(Context ctx) {
        // ctx 包含流程上下文,可读取提交的请假天数、申请人等
        int days = ctx.get("days", 0);
        String applicant = ctx.get("applicant", "");

        // 模拟审批逻辑:调用内部审批服务或直接写结果
        boolean approved = approvalService.managerApprove(applicant, days);
        ctx.set("manager_approved", approved);

        if (!approved) {
            // 审批拒绝,可以直接跳到 end 或走拒绝分支
            ctx.set("result", "rejected_by_manager");
        }
    }
}

// 部门经理审批节点
@NodeComponent("dept_review")
public class DeptReviewNode implements NodeComponent {
    @Override
    public void execute(Context ctx) {
        boolean approved = approvalService.deptApprove(
            ctx.get("applicant", ""), ctx.get("days", 0));
        ctx.set("dept_approved", approved);
        if (!approved) {
            ctx.set("result", "rejected_by_dept");
        }
    }
}

启动流程只需一行:

// 启动请假审批流程
FlowEngine engine = Solon.app().getBean(FlowEngine.class);
Context ctx = new Context();
ctx.set("applicant", "张三");
ctx.set("days", 2);  // 请假2天,预期链路:submit -> manager -> dept -> end

engine.start("leave_approval", ctx);

引擎会根据 days 的值自动走 manager_review -> dept_review -> end,跳过 vp_review。请假 5 天时,链路自动拉长到副总节点。

并行与汇合:合同审批的会签场景

请假审批是串行+条件分支,合同审批则需要并行会签。YAML 里同一个 from 下多个 to 不加互斥条件,就是并行分支:

flow:
  id: contract_approval
  nodes:
    - id: submit
    - id: legal_review      # 法务审核
    - id: finance_review    # 财务审核(金额>50万才参与)
    - id: dept_sign         # 部门会签
    - id: merge             # 汇合点
    - id: end
  chains:
    - from: submit
      to: legal_review
    - from: submit
      to: dept_sign
      when: amount > 100000
    - from: submit
      to: finance_review
      when: amount > 500000
    - from: legal_review
      to: merge
    - from: dept_sign
      to: merge
    - from: finance_review
      to: merge
    - from: merge
      to: end

merge 是汇合节点——引擎会等所有入边对应的节点完成后才推进。金额 80 万时,legal_review 和 dept_sign 并行跑完再汇合;金额 60 万时,三个节点并行,全部完成才往下走。

实践中的几个注意点

条件表达式要简单可测。 when 里的表达式(如 days > 1)由引擎内置解析器处理,支持基本比较和逻辑运算。复杂业务判断(比如"该员工是否在黑名单")不要塞进 when,放到节点逻辑里用 Java 写,YAML 只管路由。

拒绝路径要显式声明。 审批拒绝不是"流程自然结束",而是走一条明确的拒绝分支。建议在 YAML 里加一条 from: manager_review to: rejected when: manager_approved == false,拒绝节点里发通知、写日志,比隐式终止更可控。

流程上下文是线程安全的。 Context 对象随流程实例创建,节点间通过 ctx.set / ctx.get 传递数据。并行分支中不同节点写同一个 key 会冲突,建议用带节点前缀的 key(如 manager_approveddept_approved)。

YAML 和 Java 分离带来可维护性。 改审批链路只改 YAML,不动 Java 代码;改审批逻辑只改 NodeComponent,不动流程图。这种分离在审批规则频繁变动的业务里尤其有价值。

什么时候该用,什么时候不该用

适合用 Solon Flow 的场景:

  • ✅ 多步骤审批,链路随条件动态变化
  • ✅ 需要并行+汇合的编排(会签、多源抓取汇总)
  • ✅ 流程规则频繁变动,希望改配置不改代码
  • ✅ 已在用 Solon 框架的项目,接入成本极低

不适合的场景:

  • ❌ 只有两三个固定步骤,if-else 就够用,引入 DSL 反而增加理解成本
  • ❌ 需要复杂子流程嵌套、动态增删节点——当前 DSL 的表达能力有限
  • ❌ 非 Solon 生态项目——单独引入一个框架的流程组件,依赖链偏重

上手清单:

  1. 项目引入 solon-flow 依赖
  2. src/main/resources/flow/ 下写 YAML 流程定义
  3. 为每个节点写 @NodeComponent 实现类
  4. 注入 FlowEngine,调用 start 启动流程
  5. ctx 传业务数据,用 when 控制路由

50 行 YAML 画完图,几个 Java 类填完逻辑,审批流就能跑起来。比起三层 if-else 嵌套,这张有向图一眼就能看出谁审批、什么条件跳过谁、拒绝走哪条路——这才是流程编排该有的样子。


相关推荐