当前位置: 首页 > article >正文

规则引擎LiteFlow

规则引擎LiteFlow

1.简介

官网:https://liteflow.cc/pages/5816c5/

在每个公司的系统中,总有一些拥有复杂业务逻辑的系统,这些系统承载着核心业务逻辑,几乎每个需求都和这些核心业务有关,这些核心业务业务逻辑冗长,涉及内部逻辑运算,缓存操作,持久化操作,外部资源调取,内部其他系统RPC调用等等。时间一长,项目几经易手,维护成本就会越来越高。各种硬代码判断,分支条件越来越多。代码的抽象,复用率也越来越低,各个模块之间的耦合度很高。一小段逻辑的变动,会影响到其他模块,需要进行完整回归测试来验证。如要灵活改变业务流程的顺序,则要进行代码大改动进行抽象,重新写方法。实时热变更业务流程,几乎很难实现。

如何打破僵局?LiteFlow为解耦逻辑而生,为编排而生,在使用LiteFlow之后,你会发现打造一个低耦合,灵活的系统会变得易如反掌!

LiteFlow是一个非常强大的现代化的规则引擎框架,融合了编排特性和规则引擎的所有特性。

2.依赖

LiteFlow要求的Springboot的最低的版本是2.0。

支持的范围是Springboot 2.X ~ Springboot 3.X。

当然如果你使用了最新的Springboot 3.X,相应的JDK版本也要切换为JDK17。

示例:版本号可以改动

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

3.配置项

liteflow:
  #规则文件路径
  rule-source: config/flow.el.xml
  #-----------------以下非必须-----------------
  #liteflow是否开启,默认为true
  enable: true
  #liteflow的banner打印是否开启,默认为true
  print-banner: true
  #zkNode的节点,只有使用zk作为配置源的时候才起作用,默认为/lite-flow/flow
  zk-node: /lite-flow/flow
  #上下文的最大数量槽,默认值为1024
  slot-size: 1024
  #FlowExecutor的execute2Future的线程数,默认为64
  main-executor-works: 64
  #FlowExecutor的execute2Future的自定义线程池Builder,LiteFlow提供了默认的Builder
  main-executor-class: com.yomahub.liteflow.thread.LiteFlowDefaultMainExecutorBuilder
  #自定义请求ID的生成类,LiteFlow提供了默认的生成类
  request-id-generator-class: com.yomahub.liteflow.flow.id.DefaultRequestIdGenerator
  #并行节点的线程池Builder,LiteFlow提供了默认的Builder
  thread-executor-class: com.yomahub.liteflow.thread.LiteFlowDefaultWhenExecutorBuilder
  #异步线程最长的等待时间(只用于when),默认值为15000
  when-max-wait-time: 15000
  #异步线程最长的等待时间(只用于when),默认值为MILLISECONDS,毫秒
  when-max-wait-time-unit: MILLISECONDS
  #when节点全局异步线程池最大线程数,默认为16
  when-max-workers: 16
  #并行循环子项线程池最大线程数,默认为16
  parallel-max-workers: 16
  #并行循环子项线程池等待队列数,默认为512
  parallel-queue-limit: 512
  #并行循环子项的线程池Builder,LiteFlow提供了默认的Builder
  parallel-loop-executor-class: com.yomahub.liteflow.thread.LiteFlowDefaultParallelLoopExecutorBuilder
  #when节点全局异步线程池等待队列数,默认为512
  when-queue-limit: 512
  #设置解析模式,一共有三种模式,PARSE_ALL_ON_START | PARSE_ALL_ON_FIRST_EXEC | PARSE_ONE_ON_FIRST_EXEC
  parse-mode: PARSE_ALL_ON_START
  #全局重试次数,默认为0
  retry-count: 0
  #是否支持不同类型的加载方式混用,默认为false
  support-multiple-type: false
  #全局默认节点执行器
  node-executor-class: com.yomahub.liteflow.flow.executor.DefaultNodeExecutor
  #是否打印执行中过程中的日志,默认为true
  print-execution-log: true
  #是否开启本地文件监听,默认为false
  enable-monitor-file: false
  #是否开启快速解析模式,默认为false
  fast-load: false
  #简易监控配置选项
  monitor:
    #监控是否开启,默认不开启
    enable-log: false
    #监控队列存储大小,默认值为200
    queue-limit: 200
    #监控一开始延迟多少执行,默认值为300000毫秒,也就是5分钟
    delay: 300000
    #监控日志打印每过多少时间执行一次,默认值为300000毫秒,也就是5分钟
    period: 300000

上面是官网给出的详细配置项,具体可以参考,下面是我项目里使用到的配置项

liteflow:
  # 指定规则文件路径
  ruleSource : liteflow/*.el.xml
  # 重试次数
  retry-count: 0
  print-execution-log: true
  monitor:
    #监控是否开启,默认不开启
    enable-log: true
    #监控队列存储大小,默认值为200
    period: 300000
    #自定义请求ID的生成类
  request-id-generator-class: com.llp.liteflow.config.AppRequestIdGenerator
  # 上下文的最大数量槽
  slot-size : 10240
  # 线程数,默认为64
  main-executor-works: 64
  # when 节点全局异步线程池最大线程数
  when-max-workers: 16
  # when 节点全局异步线程池队列数
  when-queue-limit: 5120
  # 在启动的时候就解析规则
  parse-on-start: true
  enable: true

4.代码实现

自定义请求ID的生成类

@Data
public class AppRequestIdGenerator implements RequestIdGenerator {

    public static final Snowflake flake = new Snowflake();

    @Override
    public String generate() {
        return flake.nextIdStr();
    }
}

上下文

@Data
public class AppFlowContext {

    private String text;

}

编写规则表达式

参考https://liteflow.cc/pages/a590ee/#%E5%9F%BA%E6%9C%AC%E7%94%A8%E6%B3%95

orderFlow.el.xml

<?xml version="1.0" encoding="UTF-8"?>
<flow>
    <!--
    1.验证用户信息:确保用户登录状态有效。
    2.准备交易:生成订单并锁定库存。
    3.处理支付:调用支付网关完成支付。
    4.更新订单状态:根据支付结果更新订单状态。
    5.发送通知:通过邮件或短信通知用户支付结果。
    -->
    <chain name="orderFlow">
        THEN(
        verifyUser,
        prepareTrade,
        processPayment,
        updateOrderStatus,
        WHEN(sendEmail, sendPhone)
        );
    </chain>
</flow>

<!--        # 文件编排, then 代表串行执行  when 表示并行执行-->
<!--        # 串行编排示例:同步执行-->
<!--        THEN(a, b, c, d);-->
<!--        # 并行编排示例:异步执行-->
<!--        WHEN(a, b, c);-->
<!--        # 串行和并行嵌套结合-->
<!--        THEN( a, WHEN(b, c, d), e);-->
<!--        # 选择编排示例: 通过组件a的返回值决定执行哪一个组件,如果a组件执行返回的组件名称是b则执行b-->
<!--        SWITCH(a).to(b, c, d);-->
<!--        # 条件编排示例 IF(x, a) x组件返回true时执行a-->
<!--        THEN(IF(x, a),b );-->

规则类

这里一共将业务校验拆分为了四个规则分别去处理:

1.验证用户信息:确保用户登录状态有效。
2.准备交易:生成订单并锁定库存。
3.处理支付:调用支付网关完成支付。
4.更新订单状态:根据支付结果更新订单状态。
5.发送通知:通过邮件或短信通知用户支付结果。

verifyUser

@Slf4j
//注意这里组件的名称要和前面的名称一致
@Component(value = "verifyUser")
public class VerifyUser extends NodeComponent {
    @Override
    public void process() throws Exception {
        log.info("校验用户信息");
        OrderReqVO requestData = this.getSlot().getRequestData();
        log.info("requestData:{}",requestData);

        /**
         *在前面orderServiceImpl类中指定了上下文的类型,所以这里可以直接获取到上下文对象
         * 并对上下文对象进行操作
         */
        AppFlowContext context = this.getContextBean(AppFlowContext.class);
        context.setText("verifyUser");
    }
}

prepareTrade

@Slf4j
@Component(value = "prepareTrade")
public class PrepareTrade  extends NodeComponent {
    @Override
    public void process() throws Exception {
        log.info("准备交易");
        OrderReqVO requestData = this.getSlot().getRequestData();
        log.info("requestData:{}",requestData);
        AppFlowContext context = this.getContextBean(AppFlowContext.class);
        log.info("context:{}",context);
    }
}

processPayment

@Slf4j
@Component(value = "processPayment")
public class ProcessPayment extends NodeComponent {
    @Override
    public void process() throws Exception {
        log.info("处理支付");

    }
}

updateOrderStatus

@Slf4j
@Component(value = "updateOrderStatus")
public class UpdateOrderStatus  extends NodeComponent {


    @Override
    public void process() throws Exception {
        log.info("更新订单状态");

    }
}

sendEmail

@Slf4j
@Component(value = "sendEmail")
public class SendEmail  extends NodeComponent {
    @Override
    public void process() throws Exception {
        log.info("发送邮件");

    }
}

sendPhone

@Slf4j
@Component(value = "sendPhone")
public class SendPhone extends NodeComponent {
    @Override
    public void process() throws Exception {
        log.info("发送手机短信");
    }
}

5.测试

/**
 * 参考:https://blog.csdn.net/zhangguicai168/article/details/140726102
 */
@SpringBootApplication
public class LiteFlowApplication {

    public static void main(String[] args) {
        SpringApplication.run(LiteFlowApplication.class, args);
    }

}

@Slf4j
@RestController
public class OrderController {

    @Resource
    private OrderService orderService;

    /**
     * 模拟订单支付流程信息
     */
    @PostMapping(value = "/pay")
    public String flow(@RequestBody OrderReqVO reqVO) {
        orderService.handleApp(reqVO);
        return "success";
    }

}
@Slf4j
@Service
public class OrderServiceImpl implements OrderService {

    @Resource
    private FlowExecutor flowExecutor;

    @Override
    public void handleApp(OrderReqVO reqVO) {
        //对应规则名称,我们可以将前置的业务校验使用liteflow去处理,后面只关注业务的实现
        LiteflowResponse response = flowExecutor.execute2Resp("orderFlow", reqVO, AppFlowContext.class);

        // 获取流程执行后的结果
        if (!response.isSuccess()) {
            Exception e = response.getCause();
            log.warn(" error is {}", e.getCause(), e);
        }

        // 获取流程执行后的上下文信息
        AppFlowContext context = response.getContextBean(AppFlowContext.class);
        log.info("handleApp 执行完成后 context {}", JSONUtil.toJsonStr(context));
    }
}

执行打印信息如下:

2025-02-05 10:47:39.433  INFO 27332 --- [nio-8081-exec-3] com.llp.liteflow.rule.VerifyUser         : 校验用户信息

2025-02-05 10:47:39.436  INFO 27332 --- [nio-8081-exec-3] com.llp.liteflow.rule.PrepareTrade       : 准备交易

2025-02-05 10:47:39.436  INFO 27332 --- [nio-8081-exec-3] com.llp.liteflow.rule.ProcessPayment     : 处理支付

2025-02-05 10:47:39.436  INFO 27332 --- [nio-8081-exec-3] com.llp.liteflow.rule.UpdateOrderStatus  : 更新订单状态

# 这里发送邮件和短信是并行处理
2025-02-05 10:47:39.451  INFO 27332 --- [lf-when-thead-0] com.llp.liteflow.rule.SendEmail          : 发送邮件

2025-02-05 10:47:39.452  INFO 27332 --- [lf-when-thead-1] com.llp.liteflow.rule.SendPhone          : 发送手机短信

http://www.kler.cn/a/535427.html

相关文章:

  • Python利用VideoCapture和FFmpeg读取多个rtsp流性能的比较
  • nuxt3中使用useFetch请求刷新不返回数据或返回html结构问题解决-完整nuxt3useFetchtch请求封装
  • Text2Sql:开启自然语言与数据库交互新时代(3030)
  • 使用多模态大语言模型进行深度学习的图像、文本和语音数据增强
  • Java 中的异常处理机制是如何工作的?请解释 try-catch-finally语句块的作用 ?
  • 为什么使用nohup 和 启动的python脚本,日志没有在nohup.out中
  • Python----Python高级(并发编程:线程Thread,多线程,线程间通信,线程同步,线程池)
  • 尚硅谷spring框架视频教程——学习笔记二(数据库、事务、webflux)
  • [实验日志] VS Code 连接服务器上的 Python 解释器进行远程调试
  • node.js的require()
  • 低至3折,百度智能云千帆宣布全面支持DeepSeek-R1/V3调用
  • Web3.0 技术应用溯源系统建设
  • MS17-010(永恒之蓝1.0)漏洞远程控制win7系统操作实战小白通俗易懂
  • 如何使用sqlalchemy的orm模式构建表结构1对1,1对多,多对多的关系
  • 如何打造一个更友好的网站结构?
  • Vue组件开发——进阶篇
  • OS10 固件更新步骤-U 盘方式
  • SQL 中的谓词逻辑
  • PHP商会招商项目系统小程序
  • CentOS服务器部署Docker+Jenkins持续集成环境
  • 微信小程序调用企业微信客户服务插件联通企业微信客服
  • 【Elasticsearch】geotile grid聚合
  • Python Bug修复案例分析:列表切片引发的内存泄漏问题
  • DeepSeek R1 Distill Llama 70B(免费版)API使用详解
  • CSS Position(定位)详解及举例说明
  • C#迭代器和Unity的Coroutine原理