Spring Boot 集成 LiteFlow:支付价格流程编排实战

在电商、支付类系统中,价格计算、订单创建、优惠叠加等业务流程往往步骤多、规则变动频繁。传统硬编码会出现大量if-else嵌套、长方法臃肿、改流程就要改代码重部署等问题,维护成本极高。

LiteFlow 是一款轻量级、高性能的 Java 流程编排规则引擎,主打组件化拆分、规则化编排、支持热更新 ,非常适合支付、订单、营销这类流程多变的业务场景。本文结合商品价格计算实战案例,从原理、核心语法、代码实现到运行演示,完整讲解 LiteFlow 在支付场景下的落地使用。

一、LiteFlow 核心介绍

1. 什么是 LiteFlow

LiteFlow 是面向业务步骤编排 的规则引擎,区别于 Flowable、Activiti 这类偏重人工审批的工作流框架。它的核心思想是将业务步骤拆分为独立组件,通过 EL 表达式编排执行流程,规则与代码解耦。

核心优势:

  • 组件解耦:每个业务步骤独立成组件,单一职责,可复用、易测试;

  • 规则驱动:流程顺序、分支、并行全部由配置文件定义,调整流程无需改动业务代码;

  • 秒级热更新:支持本地文件、配置中心、数据库存储规则,线上修改规则即时生效,无需重启服务;

  • 语法简洁:内置串行、并行、条件分支、循环、异常捕获等丰富 EL 语法,覆盖绝大多数业务场景。

2. 核心设计思想:工作台模式

理解 LiteFlow 只需抓住三个核心概念:

  1. 组件(Component):对应每一个独立业务逻辑,如同 "工人",只负责自身逻辑;

  2. 上下文(Context):全局唯一的数据载体,相当于 "工作台",所有组件的数据交互都通过上下文完成,组件之间互不直接调用;

  3. 规则(Rule):定义组件的执行顺序、逻辑关系,相当于 "工序流程"。

这套模式彻底实现逻辑解耦,新增、删除、调整步骤都不会影响原有组件。

3. 主流框架对比

|-------------------|----------|-------------------------|
| 框架 | 定位 | 适用场景 |
| LiteFlow | 业务流程编排引擎 | 价格计算、订单链路、风控、营销规则等步骤型流程 |
| Flowable/Activiti | 工作流引擎 | 人工审批、任务流转、多级工单 |
| Drools | 规则推理引擎 | 复杂条件判断、策略推理,语法较重 |
| 纯硬编码 / 策略模式 | 原生代码实现 | 简单固定流程,流程极少变更 |

总结 :支付、订单这类步骤多、变动频繁的流程,优先选择 LiteFlow。

4. 核心 EL 关键字(常用)

LiteFlow 通过极简 EL 表达式编排流程,掌握以下关键字即可覆盖 90% 业务场景:

  • THEN:串行执行,组件按顺序依次运行;

  • WHEN:并行执行,多个组件同时运行;

  • IF:条件分支,满足条件走第一个分支,否则走第二个分支;

  • SWITCH:路由分支,根据结果路由到不同组件;

  • FOR/ITERATOR:循环执行;

  • CATCH:异常捕获、重试、兜底降级。


二、组件生命周期四大法宝(你要补充的重点)

在实际支付、订单类业务中,我们经常需要:

  • 组件执行成功后做一些收尾工作

  • 组件异常时统一日志、告警

  • 根据业务条件跳过某些组件

  • 组件报错后是否继续执行后续流程

LiteFlow 提供 4 个非常实用的方法:

1. onSuccess()

组件执行成功后自动调用,适合:记录日志、埋点、数据后置处理。

2. onError(Exception e)

组件抛出异常时自动调用,适合:异常日志、告警、上报、数据回滚。

3. isAccess()

控制组件是否执行

  • return true → 执行

  • return false → 直接跳过该组件

非常适合优惠活动开关、会员等级判断、功能灰度。

4. isContinueOnError()

组件报错后流程是否继续往下走

  • return true(默认):报错后继续执行后续组件

  • return false:报错后立即终止整个流程

支付、风控场景必须用它保证数据安全。


三、业务场景说明

本文以电商支付价格计算为实战场景,完整流程如下:

  1. calcBase:计算商品基础价格;

  2. isVip:判断用户是否为 VIP,走不同优惠逻辑;

    1. VIP 用户:执行vipDiscount(VIP 折扣);

    2. 普通用户:执行couponDiscount(优惠券抵扣);

  3. 并行执行两个优惠计算:fullReduction(满减)、pointsDeduct(积分抵扣);

  4. calcFinal:汇总所有优惠,计算最终支付价格。

对应 LiteFlow 规则表达式:

复制代码
THEN(
  calcBase,
  IF(isVip, vipDiscount, couponDiscount),
  WHEN(fullReduction, pointsDeduct),
  calcFinal
)

四、完整代码实现

1. 项目环境与依赖

java 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.15</version>
        <relativePath/>
    </parent>

    <groupId>com.pay</groupId>
    <artifactId>liteflow-price-demo</artifactId>
    <version>1.0.0</version>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>com.yomahub</groupId>
            <artifactId>liteflow-spring-boot-starter</artifactId>
            <version>2.12.0</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
</project>

2. 配置 application.yml

java 复制代码
liteflow:
  rule-source: config/flow.el.xml
  print-banner: false

3. 流程上下文 OrderContext

java 复制代码
import com.yomahub.liteflow.context.ContextBean;
import lombok.Data;

@Data
@ContextBean("orderCtx")
public class OrderContext {
    private Integer originalPrice;
    private boolean isVip;
    private Integer basePrice;
    private Integer discountPrice;
    private Integer fullReduce;
    private Integer pointsDeduct;
    private Integer finalPrice;
}

五、带生命周期的完整组件(你要的 4 个方法全部加上)

我以 calcBase 组件为例,把 4 个方法完整写进去,其他组件同理可复用。

1. calcBase 计算基础价格(完整版生命周期)

java 复制代码
import com.yomahub.liteflow.core.NodeComponent;
import org.springframework.stereotype.Component;

@Component("calcBase")
public class CalcBaseCmp extends NodeComponent {

    @Override
    public void process() {
        OrderContext ctx = getContextBean(OrderContext.class);
        ctx.setBasePrice(ctx.getOriginalPrice());
        System.out.println("1. 计算基础价格:" + ctx.getBasePrice());
    }

    // ==================== 生命周期 4 大方法 ====================

    /**
     * 组件执行成功后回调
     */
    @Override
    public void onSuccess() {
        System.out.println("[生命周期] calcBase 执行成功");
    }

    /**
     * 组件异常时回调
     */
    @Override
    public void onError(Exception e) {
        System.err.println("[生命周期] calcBase 执行失败:" + e.getMessage());
    }

    /**
     * 组件是否执行:返回 false 则跳过
     */
    @Override
    public boolean isAccess() {
        OrderContext ctx = getContextBean(OrderContext.class);
        // 示例:原价不为空才执行
        boolean canExec = ctx.getOriginalPrice() != null && ctx.getOriginalPrice() > 0;
        System.out.println("[生命周期] calcBase 是否允许执行:" + canExec);
        return canExec;
    }

    /**
     * 报错后是否继续执行整个流程
     * true:继续(默认)
     * false:立即终止流程(支付场景常用)
     */
    @Override
    public boolean isContinueOnError() {
        // 基础价格计算失败,整个支付必须终止
        return false;
    }
}

2. isVip 判断组件

java 复制代码
import com.yomahub.liteflow.core.NodeIfComponent;
import org.springframework.stereotype.Component;

@Component("isVip")
public class IsVipCmp extends NodeIfComponent {
    @Override
    public boolean processIf() {
        OrderContext ctx = getContextBean(OrderContext.class);
        System.out.println("2. 判断是否VIP:" + ctx.isVip());
        return ctx.isVip();
    }
}

3. vipDiscount VIP 折扣

java 复制代码
import com.yomahub.liteflow.core.NodeComponent;
import org.springframework.stereotype.Component;

@Component("vipDiscount")
public class VipDiscountCmp extends NodeComponent {
    @Override
    public void process() {
        OrderContext ctx = getContextBean(OrderContext.class);
        int price = (int) (ctx.getBasePrice() * 0.8);
        ctx.setDiscountPrice(price);
        System.out.println("3. VIP折扣后价格:" + price);
    }
}

4. couponDiscount 优惠券

java 复制代码
import com.yomahub.liteflow.core.NodeComponent;
import org.springframework.stereotype.Component;

@Component("couponDiscount")
public class CouponDiscountCmp extends NodeComponent {
    @Override
    public void process() {
        OrderContext ctx = getContextBean(OrderContext.class);
        int price = ctx.getBasePrice() - 50;
        ctx.setDiscountPrice(price);
        System.out.println("3. 优惠券抵扣后价格:" + price);
    }
}

5. fullReduction 满减

java 复制代码
import com.yomahub.liteflow.core.NodeComponent;
import org.springframework.stereotype.Component;

@Component("fullReduction")
public class FullReduceCmp extends NodeComponent {
    @Override
    public void process() {
        OrderContext ctx = getContextBean(OrderContext.class);
        int reduce = ctx.getDiscountPrice() >= 200 ? 30 : 0;
        ctx.setFullReduce(reduce);
        System.out.println("4. 满减金额:" + reduce);
    }
}

6. pointsDeduct 积分抵扣

java 复制代码
import com.yomahub.liteflow.core.NodeComponent;
import org.springframework.stereotype.Component;

@Component("pointsDeduct")
public class PointsDeductCmp extends NodeComponent {
    @Override
    public void process() {
        OrderContext ctx = getContextBean(OrderContext.class);
        ctx.setPointsDeduct(20);
        System.out.println("4. 积分抵扣:20");
    }
}

7. calcFinal 最终价格

java 复制代码
import com.yomahub.liteflow.core.NodeComponent;
import org.springframework.stereotype.Component;

@Component("calcFinal")
public class CalcFinalCmp extends NodeComponent {
    @Override
    public void process() {
        OrderContext ctx = getContextBean(OrderContext.class);
        int finalPrice = ctx.getDiscountPrice() - ctx.getFullReduce() - ctx.getPointsDeduct();
        ctx.setFinalPrice(finalPrice);
        System.out.println("5. 最终支付价格:" + finalPrice);
    }
}

六、规则文件 flow.el.xml

java 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<flow>
    <chain name="priceChain">
        THEN(
          calcBase,
          IF(isVip, vipDiscount, couponDiscount),
          WHEN(fullReduction, pointsDeduct),
          calcFinal
        )
    </chain>
</flow>

七、启动测试类

java 复制代码
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.flow.LiteflowResponse;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;

@SpringBootApplication
public class LiteFlowPriceApplication {
    public static void main(String[] args) {
        ApplicationContext context = SpringApplication.run(LiteFlowPriceApplication.class, args);
        FlowExecutor executor = context.getBean(FlowExecutor.class);

        OrderContext ctx = new OrderContext();
        ctx.setOriginalPrice(300);
        ctx.setVip(true);

        LiteflowResponse response = executor.execute2Resp("priceChain", null, ctx);
        OrderContext result = response.getContextBean(OrderContext.class);

        System.out.println("\n===== 支付结果 =====");
        System.out.println("最终支付:" + result.getFinalPrice());
    }
}

八、运行效果(包含生命周期日志)

java 复制代码
[生命周期] calcBase 是否允许执行:true
1. 计算基础价格:300
[生命周期] calcBase 执行成功
2. 判断是否VIP:true
3. VIP折扣后价格:240
4. 满减金额:30
4. 积分抵扣:20
5. 最终支付价格:190

===== 支付结果 =====
最终支付:190

九、生命周期 4 个方法总结(博客必备)

1. onSuccess()

组件执行成功后自动调用,用于日志、埋点、数据收尾

2. onError(Exception e)

组件抛出异常时自动调用,用于异常日志、告警、回滚

3. isAccess()

返回 true 执行,返回 false 跳过。 适合:活动开关、会员权限、功能灰度、条件执行

4. isContinueOnError()

  • false :组件报错(异常) → 整个流程立即终止(支付、风控、订单必须用)

  • true :组件报错(异常) → 继续执行后续流程(日志、通知类可用)


相关推荐
金融支付架构实战指南3 天前
Redisson 组件 + 支付业务场景落地对照表
支付·分布式锁·redisson·锁续期·锁超时
nix.gnehc1 个月前
从入门到源码:LiteFlow 规则引擎完全指南
liteflow
庞轩px2 个月前
初探OA开发:从企业信息化到国产化替代的技术实践
流程引擎·国产化·oa
踏雪羽翼2 个月前
android 实现google 订阅支付
android·支付·订阅·google订阅·谷歌支付
jiayong233 个月前
流程设计器技术选型评估报告
运维·ubuntu·流程引擎
分享牛4 个月前
Camunda 7停止维护后,bpm开源流程引擎新局面
流程图·流程引擎·bpmn·cmmn
青茶3604 个月前
支付宝支付 报错 invalid [default store dir]: /tmp/
支付·支付宝
东边有耳5 个月前
图文:银行核心账务处理逻辑(白话篇)
架构·银行·支付
东边有耳6 个月前
小额支付系统:详细处理逻辑(底层)
架构·银行·支付