找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

1711

积分

0

好友

225

主题
发表于 14 小时前 | 查看: 3| 回复: 0

mall学习教程项目页面截图

在开发业务系统时,我们时常会遇到复杂的业务处理流程。如果单纯使用 if-else 来实现,代码不仅冗长,后期维护和迭代也相当困难。有没有一种优雅的方式来编排这些业务组件呢?今天介绍一个轻量级但功能强大的国产流程引擎框架——LiteFlow。本文将以电商业务中典型的订单价格计算场景为例,手把手带你体验如何用它来清晰、灵活地组织业务逻辑。

LiteFlow简介

LiteFlow是一个专为组件化业务编排设计的轻量级流程引擎。它的核心思想是将业务逻辑拆分为独立的组件,然后通过一份简洁易懂的规则文件将这些组件串联起来,从而构建出完整的业务流。这非常适合处理步骤繁多、带有条件分支的复杂业务场景。

LiteFlow拥有以下主要特性:

  • 组件定义统一:所有业务逻辑都被封装为组件,使用Spring原生的 @Component 注解即可定义。
  • 规则轻量易学:基于规则文件进行流程编排,其表达式语言简单直观,上手仅需几分钟。
  • 规则格式多样:支持XML、JSON、YML三种格式的规则文件,可按团队喜好选择。
  • 编排能力强大:支持串行、并行、选择、条件分支等多种编排模式,并能混合编排同步与异步组件。
  • 热刷新支持:规则文件修改后无需重启应用,可实现实时生效。
  • 兼容性良好:完美支持SpringBoot及非Spring环境的Java项目。

下图展示了使用LiteFlow实现的订单价格计算引擎的前端界面,计算过程涉及会员折扣、多种促销、运费等十多个步骤,逻辑清晰,结果一目了然。

订单价格计算请求与结果明细

强大的IDEA插件:LiteFlowX

为了提升开发体验,LiteFlow提供了专属的IDEA插件——LiteFlowX。它极大地增强了规则文件编写的便捷性,强烈推荐安装使用。

  1. 安装插件:在IDEA的插件市场(Plugins Marketplace)中搜索“LiteFlowX”并安装。
    IDEA插件市场中的LiteFlowX插件详情
  2. 图标识别:安装后,项目中定义的LiteFlow组件和规则文件会显示特定的图标,便于快速识别。
    项目文件结构,标注了组件与规则文件
  3. 智能提示与跳转:编辑规则文件时,插件会提供已定义组件的代码补全提示,并支持在组件类与规则文件之间快速跳转。
    XML规则文件编辑时的组件自动补全提示
  4. 工具箱:插件右侧提供了一个工具箱,可以便捷地查看项目中所有的组件和流程链(Chain)。
    LiteFlowX工具箱界面,展示组件与链列表

规则表达式快速入门

LiteFlow的核心在于其规则表达式,它们被定义在规则文件中。掌握下面几种基本的编排模式,你就能应对大多数业务场景。

串行编排 (THEN)

依次执行组件a, b, c, d。

<chain name="chain1">
    THEN(a, b, c, d);
</chain>

并行编排 (WHEN)

并行执行组件a, b, c。

<chain name="chain1">
    WHEN(a, b, c);
</chain>

选择编排 (SWITCH)

实现类似switch的逻辑,根据组件a的返回结果,决定执行b, c, d中的哪一个。

<chain name="chain1">
    SWITCH(a).to(b, c, d);
</chain>

条件编排 (IF/ELIF/ELSE)

实现if-elseif-else的条件分支逻辑。

<!-- if -->
<chain name="chain1">
    IF(x, a);
</chain>

<!-- 三元运算符 if-else -->
<chain name="chain1">
    IF(x, a, b);
</chain>

<!-- if-else (等价于上一句) -->
<chain name="chain1">
    IF(x, a).ELSE(b);
</chain>

<!-- if-elseif-else -->
<chain name="chain1">
    IF(x1, a).ELIF(x2, b).ELSE(c);
</chain>

使用子流程

对于复杂流程,可以定义子流程(子链),然后在主流程中引用,使结构更清晰。

<!-- 定义子流程 -->
<chain name="subChain">
   THEN(C, D);
</chain>

<!-- 主流程中引用 -->
<chain name="mainChain">
    THEN(
     A, B,
     subChain, <!-- 引用子流程 -->
     E
    );
</chain>

实战:订单价格计算引擎

了解了基本语法后,我们通过一个实际的订单价格计算案例,来看看LiteFlow如何落地。该案例模拟了电商中计算订单最终价格的完整流程,涉及参数检查、优惠转换、折扣计算、运费判断等十多个步骤。

1. 项目集成

在SpringBoot项目中,只需添加以下依赖:

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

application.yml 中配置规则文件路径:

server:
  port: 8580
liteflow:
  #规则文件路径
  rule-source: liteflow/*.el.xml

2. 案例结构与流程

我们将使用LiteFlow官方提供的示例项目 liteflow-example(项目地址见文末)。运行后访问 http://localhost:8580 即可体验。

其核心业务流程如下图所示,清晰地展示了从订单数据输入到最终价格输出的完整组件化流程:
订单价格计算流程图

3. 定义业务组件

每个计算步骤都被抽象为一个独立的组件。例如,优惠券计算组件

/**
 * 优惠券抵扣计算组件
 */
@Component("couponCmp")
public class CouponCmp extends NodeComponent {
    @Override
    public void process() throws Exception {
        PriceContext context = this.getContextBean(PriceContext.class);
        // Mock优惠券面值
        Long couponId = context.getCouponId();
        BigDecimal couponPrice = new BigDecimal(15);
        // 计算逻辑...
        BigDecimal prePrice = context.getLastestPriceStep().getCurrPrice();
        BigDecimal currPrice = prePrice.subtract(couponPrice);
        // 将步骤结果存入上下文
        context.addPriceStep(new PriceStepVO(PriceTypeEnum.COUPON_DISCOUNT,
                couponId.toString(),
                prePrice,
                currPrice.subtract(prePrice),
                currPrice,
                PriceTypeEnum.COUPON_DISCOUNT.getName()));
    }

    @Override
    public boolean isAccess() {
        // 根据业务条件决定是否执行此组件:有优惠券ID时才执行
        PriceContext context = this.getContextBean(PriceContext.class);
        return context.getCouponId() != null;
    }
}

对于需要条件判断的节点,如判断使用国内还是境外运费规则,需使用条件组件:

/**
 * 运费条件组件
 */
@Component("postageCondCmp")
public class PostageCondCmp extends NodeSwitchComponent {
    @Override
    public String processSwitch() throws Exception {
        PriceContext context = this.getContextBean(PriceContext.class);
        boolean oversea = context.isOversea();
        // 根据条件返回下一个要执行的组件ID
        if(oversea){
            return "overseaPostageCmp";
        }else{
            return "postageCmp";
        }
    }
}

4. 编排业务流程

定义好所有组件后,使用规则文件将它们优雅地串联起来。

首先是促销计算子流程 (promotionChain):

<?xml version="1.0" encoding="UTF-8"?>
<flow>
    <chain name="promotionChain">
        THEN(fullCutCmp, fullDiscountCmp, rushBuyCmp);
    </chain>
</flow>

然后是主流程 (mainChain),它引用了子流程,并包含了条件分支:

<?xml version="1.0" encoding="UTF-8"?>
<flow>
    <chain name="mainChain">
        THEN(
            checkCmp, slotInitCmp, priceStepInitCmp,
            promotionConvertCmp, memberDiscountCmp,
            promotionChain, couponCmp, <!-- 引用子流程 -->
            SWITCH(postageCondCmp).to(postageCmp, overseaPostageCmp), <!-- 条件分支 -->
            priceResultCmp, stepPrintCmp
        );
    </chain>
</flow>

5. 执行流程与上下文传递

在Controller中,注入 FlowExecutor 来执行定义好的流程链。

@Controller
public class PriceExampleController {
    @Resource
    private FlowExecutor flowExecutor;

    @RequestMapping(value = "/submit", method = RequestMethod.POST)
    @ResponseBody
    public String submit(@Nullable @RequestBody String reqData) {
        try {
            PriceCalcReqVO req = JSON.parseObject(reqData, PriceCalcReqVO.class);
            // 执行名为"mainChain"的流程,并传入请求参数和上下文类
            LiteflowResponse response = flowExecutor.execute2Resp("mainChain", req, PriceContext.class);
            return response.getContextBean(PriceContext.class).getPrintLog();
        } catch (Throwable t) {
            t.printStackTrace();
            return "error";
        }
    }
}

组件间如何共享数据? LiteFlow通过上下文(Context) 机制解决。所有组件都从同一个上下文对象(本例为 PriceContext)中获取输入数据和存储处理结果。例如,初始化组件将请求参数放入上下文:

@Component("slotInitCmp")
public class SlotInitCmp extends NodeComponent {
    @Override
    public void process() throws Exception {
        PriceCalcReqVO req = this.getRequestData(); // 获取请求数据
        PriceContext context = this.getContextBean(PriceContext.class);
        context.setOrderNo(req.getOrderNo());
        context.setOversea(req.isOversea());
        // ... 设置其他参数
    }
}

总结

通过上述案例可以看出,LiteFlow 将一个复杂的、多步骤且带有分支的订单价格计算逻辑,清晰地分解为多个独立的组件,并通过声明式的规则文件进行编排。这种方式带来的好处非常明显:

  1. 代码可读性高:业务流程图几乎可以直接翻译为规则文件,逻辑一目了然。
  2. 维护成本低:组件职责单一,修改或替换某个步骤不影响其他部分。
  3. 灵活性好:通过修改规则文件即可调整业务流程,无需改动代码,且支持热更新。
  4. 复用性强:定义好的组件可以在不同的流程链中复用。

对于需要处理复杂业务逻辑、追求代码整洁和可维护性的 JavaSpringBoot 项目来说,LiteFlow是一个非常值得尝试的轻量级解决方案。它学习曲线平缓,却能显著提升后端业务代码的组织能力。

项目地址

LiteFlow 开源项目地址:https://gitee.com/dromara/liteFlow
本文演示案例地址:https://gitee.com/bryan31/liteflow-example




上一篇:谷歌Magma优化器解析:随机梯度掩码如何提升LLM训练性能与鲁棒性
下一篇:管理者三大核心技能:定方向、搭班子、建机制,赋能团队高效协作与组织成长
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-2-23 19:59 , Processed in 0.335613 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表