SpringBoot中集成LiteFlow(轻量、快速、稳定可编排的组件式规则引擎)实现复杂业务解耦、动态编排、高可扩展

本文主要是介绍SpringBoot中集成LiteFlow(轻量、快速、稳定可编排的组件式规则引擎)实现复杂业务解耦、动态编排、高可扩展,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

场景

在业务开发中,经常遇到一些串行或者并行的业务流程问题,而业务之间不必存在相关性。

使用策略和模板模式的结合可以解决这个问题,但是使用编码的方式会使得文件太多,

在业务的部分环节可以这样操作,在项目角度就无法一眼洞穿其中的环节和逻辑。

一些拥有复杂业务逻辑的系统,核心业务逻辑冗长,涉及内部逻辑运算,缓存操作,持久化操作,外部资源调取,内部其他系统RPC调用等等。

时间一长,维护的成本就会越来越高。各种硬代码判断,分支条件越来越多。代码的抽象,复用率也越来越低,各个模块之间的耦合度很高。

一小段逻辑的变动,会影响到其他模块,需要进行完整回归测试来验证。

如要灵活改变业务流程的顺序,则要进行代码大改动进行抽象,重新写方法。

实时热变更业务流程,几乎很难实现 。

LiteFlow

LiteFlow就是为解耦复杂逻辑而生,如果你要对复杂业务逻辑进行新写或者重构,用LiteFlow最合适不过。

它是一个轻量,快速的组件式流程引擎框架,组件编排,帮助解耦业务代码,让每一个业务片段都是一个组件,

并支持热加载规则配置,实现即时修改。

使用LiteFlow,你需要去把复杂的业务逻辑按代码片段拆分成一个个小组件,并定义一个规则流程配置。

这样,所有的组件,就能按照你的规则配置去进行复杂的流转。

LiteFlow官方网站:

LiteFlow

LiteFlow的Gitee地址:

liteFlow: 轻量,快速,稳定,可编排的组件式规则引擎/流程引擎。拥有全新设计的DSL规则表达式。组件复用,同步/异步编排,动态编排,支持超多语言脚本,复杂嵌套规则,热部署,平滑刷新规则等等功能,让你加快开发效率!

LiteFlow的特点:

注:

博客:
霸道流氓气质-CSDN博客

实现

1、SpringBoot中集成LiteFlow

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

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

LiteFlow提供了liteflow-spring-boot-starter依赖包,提供自动装配功能

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

2、SpringBoot中配置LiteFlow

在你的SpringBoot的application.properties或者application.yml里添加配置

#liteflow规则配置文件位置
liteflow:rule-source: config/flow.el.xml

规则文件的定义

在resources下的config/flow.el.xml中定义规则:

<?xml version="1.0" encoding="UTF-8"?>
<flow><chain name="chain1">THEN(acmp, bcmp, ccmp);</chain>
</flow>

根据定义的规则,需要定义并实现一些组件,确保SpringBoot会扫描到这些组件并注册进上下文。

import com.yomahub.liteflow.core.NodeComponent;
import org.springframework.stereotype.Component;@Component("acmp")
public class ACmp extends NodeComponent {@Overridepublic void process() {//do your businessSystem.out.println("acmp执行");}
}

以此类推,定义另外两个组件

import com.yomahub.liteflow.core.NodeComponent;
import org.springframework.stereotype.Component;@Component("bcmp")
public class BCmp extends NodeComponent {@Overridepublic void process() {//do your businessSystem.out.println("bcmp执行");}
}
import com.yomahub.liteflow.core.NodeComponent;
import org.springframework.stereotype.Component;@Component("ccmp")
public class CCmp extends NodeComponent {@Overridepublic void process() {//do your businessSystem.out.println("ccmp执行");}
}

更多配置项内容参考文档说明

🌿Springboot下的配置项 | LiteFlow

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

3、SpringBoot中执行LiteFlow

声明启动类,确保定义的组件扫入Spring上下文

@SpringBootApplication
//把你定义的组件扫入Spring上下文中
@ComponentScan({"com.xxx.xxx.cmp"})
public class LiteflowExampleApplication {public static void main(String[] args) {SpringApplication.run(LiteflowExampleApplication.class, args);}
}

然后可以在在Springboot任意被Spring托管的类中拿到flowExecutor,进行执行链路

这里进行单元测试

import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.flow.LiteflowResponse;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;@RunWith(SpringRunner.class)
@SpringBootTest(classes = RuoYiApplication.class,webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class LiteFlowTest {@Resourceprivate FlowExecutor flowExecutor;@Testpublic void helloLiteFlow() {LiteflowResponse response = flowExecutor.execute2Resp("chain1");System.out.println(response);}
}

这里的chain1与上面规则文件中的对应。

运行结果

可以看到三个组件依次执行,这是因为配置的规则文件中配置的规则如此。

除了上面配置的普通组件之外,还可配置其他组件,比如选择组件、条件组件、循环组件等

📎普通组件 | LiteFlow

下面配置一个选择组件为例

在实际业务中,往往要通过动态的业务逻辑判断到底接下去该执行哪一个节点,这就引申出了选择节点,

选择节点可以用于SWITCH关键字中。

关于SWITCH表达式的用法,可以参考选择编排一章。

选择节点a需要继承NodeSwitchComponent。

需要实现方法processSwitch方法

import com.yomahub.liteflow.core.NodeSwitchComponent;
import org.springframework.stereotype.Component;@Component("switchCmp")
public class SwitchCmp extends NodeSwitchComponent {@Overridepublic String processSwitch() throws Exception {System.out.println("switchCmp executed!");//自己业务选择//以下代表选择了switchCmpA节点return "switchCmpA";}
}

配置规则文件

<?xml version="1.0" encoding="UTF-8"?>
<flow><chain name="chain1">THEN(acmp, bcmp, ccmp);</chain><chain name="switch_chain">SWITCH(switchCmp).to(switchCmpA, switchCmpB);</chain>
</flow>

其中switchCmpA与switchCmpB是普通组件

编写单元测试

    @Testpublic void switchTest() {LiteflowResponse response = flowExecutor.execute2Resp("switch_chain");}

运行结果

条件组件用法

LiteFlow从2.8.5版本开始,提供了条件组件的定义。

条件组件,也可以称之为IF组件,返回是一个true/false。可用于IF...ELIF...ELSE等关键字。

关于IF...ELIF...ELSE表达式的用法,可以参考条件编排这一章。

比如一个IF三元表达式,如下所示,xcmp就是IF组件,为真,执行acmp,为假,执行bcmp:

    <chain name="if_chain">IF(xcmp, acmp, bcmp);</chain>

编写条件组件

import com.yomahub.liteflow.core.NodeIfComponent;
import org.springframework.stereotype.Component;@Component("xcmp")
public class XCmp extends NodeIfComponent {@Overridepublic boolean processIf() throws Exception {//自己的业务判断return false;}
}

其它更多组件用法参考官方文档。

4、LiteFlow组件传参

在一个流程中,总会有一些初始的参数,比如订单号,用户Id等等一些的初始参数。

这时候需要通过以下方法的第二个参数传入

public LiteflowResponse execute2Resp(String chainId, Object param, Class<?>... contextBeanClazzArray)

这个流程入参,可以是任何对象,一般生产业务场景下,你可以把自己封装好的Bean传入。

编写传参组件

import com.ruoyi.system.domain.BusStudent;
import com.yomahub.liteflow.core.NodeIfComponent;
import org.springframework.stereotype.Component;@Component("xpcmp")
public class XParamCmp extends NodeIfComponent {@Overridepublic boolean processIf() throws Exception {//自己的业务判断BusStudent requestData = this.getRequestData();if(null!=requestData.getName()&&"公众号:霸道的程序猿".equals(requestData.getName())){return true;}else{return false;}}
}

传参使用

flowExecutor.execute2Resp("if_param_chain", BusStudent.builder().name("公众号:霸道的程序猿").build());

5、LiteFlow声明式组件

普通组件和条件组件,在写法上需要你自己去定义一个类去继承NodeComponent或者NodeSwitchComponent。

这样一方面造成了耦合,另一方面由于java是单继承制,所以使用者就无法再去继承自己的类了,在自由度上就少了很多玩法。

声明式组件这一特性允许你自定义的组件不继承任何类和实现任何接口,普通的类也可以依靠注解来完成LiteFlow组件的声明。

甚至于你可以用一个类去定义多个组件,仅仅依靠注解就可以完成,这个特性也叫做方法级别式声明

类级别式声明主要用处就是通过注解形式让普通的java bean变成LiteFlow的组件。无需通过继承类或者实现接口的方式。

由于LiteFlow的组件常规方式下需要继承类来定义,使得你无法再继承自己业务的类了。这个特性可以解决这个问题。

但是和常规组件一样,需要一个类对应一个组件

自定义一个组件并使用方法级别声明

import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;@LiteflowComponent("defineCmp")
@LiteflowCmpDefine
public class DefineCmp{@LiteflowMethod(LiteFlowMethodEnum.PROCESS)public void processAcmp(NodeComponent bindCmp) {System.out.println("ACmp executed!");}@LiteflowMethod(LiteFlowMethodEnum.IS_ACCESS)public boolean isAcmpAccess(NodeComponent bindCmp){return true;}@LiteflowMethod(LiteFlowMethodEnum.BEFORE_PROCESS)public void beforeAcmp(NodeComponent bindCmp){System.out.println("before A");}@LiteflowMethod(LiteFlowMethodEnum.AFTER_PROCESS)public void afterAcmp(NodeComponent bindCmp){System.out.println("after A");}@LiteflowMethod(LiteFlowMethodEnum.ON_SUCCESS)public void onAcmpSuccess(NodeComponent bindCmp){System.out.println("Acmp success");}@LiteflowMethod(LiteFlowMethodEnum.ON_ERROR)public void onAcmpError(NodeComponent bindCmp, Exception e){System.out.println("Acmp error");}@LiteflowMethod(LiteFlowMethodEnum.IS_END)public boolean isAcmpEnd(NodeComponent bindCmp) {return false;}@LiteflowMethod(value = LiteFlowMethodEnum.ROLLBACK)public void rollbackA(NodeComponent bindCmp) throws Exception {System.out.println("ACmp rollback!");}
}

同样实现效果。

6、LiteFlow还有更多功能和属性

比如EL规则的编排

🍄说明 | LiteFlow

用代码动态构造规则

🍄说明 | LiteFlow

以及各种给高级特性、平滑热更新等。

具体参考官方文档说明。

DEMO案例

滑动验证页面

这篇关于SpringBoot中集成LiteFlow(轻量、快速、稳定可编排的组件式规则引擎)实现复杂业务解耦、动态编排、高可扩展的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/782190

相关文章

Java通过驱动包(jar包)连接MySQL数据库的步骤总结及验证方式

《Java通过驱动包(jar包)连接MySQL数据库的步骤总结及验证方式》本文详细介绍如何使用Java通过JDBC连接MySQL数据库,包括下载驱动、配置Eclipse环境、检测数据库连接等关键步骤,... 目录一、下载驱动包二、放jar包三、检测数据库连接JavaJava 如何使用 JDBC 连接 mys

SpringBoot线程池配置使用示例详解

《SpringBoot线程池配置使用示例详解》SpringBoot集成@Async注解,支持线程池参数配置(核心数、队列容量、拒绝策略等)及生命周期管理,结合监控与任务装饰器,提升异步处理效率与系统... 目录一、核心特性二、添加依赖三、参数详解四、配置线程池五、应用实践代码说明拒绝策略(Rejected

Qt使用QSqlDatabase连接MySQL实现增删改查功能

《Qt使用QSqlDatabase连接MySQL实现增删改查功能》这篇文章主要为大家详细介绍了Qt如何使用QSqlDatabase连接MySQL实现增删改查功能,文中的示例代码讲解详细,感兴趣的小伙伴... 目录一、创建数据表二、连接mysql数据库三、封装成一个完整的轻量级 ORM 风格类3.1 表结构

基于Python实现一个图片拆分工具

《基于Python实现一个图片拆分工具》这篇文章主要为大家详细介绍了如何基于Python实现一个图片拆分工具,可以根据需要的行数和列数进行拆分,感兴趣的小伙伴可以跟随小编一起学习一下... 简单介绍先自己选择输入的图片,默认是输出到项目文件夹中,可以自己选择其他的文件夹,选择需要拆分的行数和列数,可以通过

一文详解SpringBoot中控制器的动态注册与卸载

《一文详解SpringBoot中控制器的动态注册与卸载》在项目开发中,通过动态注册和卸载控制器功能,可以根据业务场景和项目需要实现功能的动态增加、删除,提高系统的灵活性和可扩展性,下面我们就来看看Sp... 目录项目结构1. 创建 Spring Boot 启动类2. 创建一个测试控制器3. 创建动态控制器注

Python中将嵌套列表扁平化的多种实现方法

《Python中将嵌套列表扁平化的多种实现方法》在Python编程中,我们常常会遇到需要将嵌套列表(即列表中包含列表)转换为一个一维的扁平列表的需求,本文将给大家介绍了多种实现这一目标的方法,需要的朋... 目录python中将嵌套列表扁平化的方法技术背景实现步骤1. 使用嵌套列表推导式2. 使用itert

Java操作Word文档的全面指南

《Java操作Word文档的全面指南》在Java开发中,操作Word文档是常见的业务需求,广泛应用于合同生成、报表输出、通知发布、法律文书生成、病历模板填写等场景,本文将全面介绍Java操作Word文... 目录简介段落页头与页脚页码表格图片批注文本框目录图表简介Word编程最重要的类是org.apach

Python使用pip工具实现包自动更新的多种方法

《Python使用pip工具实现包自动更新的多种方法》本文深入探讨了使用Python的pip工具实现包自动更新的各种方法和技术,我们将从基础概念开始,逐步介绍手动更新方法、自动化脚本编写、结合CI/C... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核

在Linux中改变echo输出颜色的实现方法

《在Linux中改变echo输出颜色的实现方法》在Linux系统的命令行环境下,为了使输出信息更加清晰、突出,便于用户快速识别和区分不同类型的信息,常常需要改变echo命令的输出颜色,所以本文给大家介... 目python录在linux中改变echo输出颜色的方法技术背景实现步骤使用ANSI转义码使用tpu

Spring Boot中WebSocket常用使用方法详解

《SpringBoot中WebSocket常用使用方法详解》本文从WebSocket的基础概念出发,详细介绍了SpringBoot集成WebSocket的步骤,并重点讲解了常用的使用方法,包括简单消... 目录一、WebSocket基础概念1.1 什么是WebSocket1.2 WebSocket与HTTP