liteflow学习一

简介: liteflow学习一

liteflow的业务逻辑编排能力是非常强,同时也是非常好用的。支持很多种方式的编排,串行编排、并行编排、选择编排、条件编排、循环编排,同时支持使用子流程、使用子变量等等。本文参考liteflow官网,学习liteflow的执行流程,官网对学习liteflow非常友好。

liteflow的开源地址:https://gitee.com/dromara/liteFlow,很感谢作者铂赛东开源这么好用的业务编排框架。

一、liteflow的使用

首先引入liteflow的spring-boot-starter依赖,然后继承 NodeComponent,重写process方法。在application.yml中配置xml中配置资源规则,以说明当前串行器的执行顺序。

比如当前的执行顺序是a->b->c

<?xml version="1.0" encoding="UTF-8"?>
<flow>
    <chain name="chain1">
        THEN(a, b, c);
    </chain>
</flow>

在业务系统的业务逻辑层注入FlowExecutor,chain1在业务逻辑执行对应的业务逻辑,也即这个顺序是a->b->c,也即 NodeComponent中的业务逻辑,Bean对应@Component("a")、@Component("b")、@Component("c")。

@Component
public class YourClass{
    @Resource
    private FlowExecutor flowExecutor;
    public void testConfig(){
        LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
    }
}

完成编写后,即可执行,执行的顺序a->b->c串行编排。也即执行后可以看到我们想要的结果。

这样简化了我们组装业务逻辑的方式。

这么方便使用,是不是非常好奇怎么实现的呢?

二、如何实现

首先我们还是从example开始,从最基础的builder开始学习。


在脚本中,串行器以THEN开头,而并行器以WHEN开头。

@Test
    public void testBuilder() throws Exception {
        // 基于liteflowNode构建器创建节点
        LiteFlowNodeBuilder.createNode()
            .setId("a")
            .setName("组件A")
            .setType(NodeTypeEnum.COMMON)
            .setClazz("com.yomahub.liteflow.test.builder.cmp1.ACmp")
            .build();
        LiteFlowNodeBuilder.createNode()
            .setId("b")
            .setName("组件B")
            .setType(NodeTypeEnum.COMMON)
            .setClazz("com.yomahub.liteflow.test.builder.cmp1.BCmp")
            .build();
        LiteFlowNodeBuilder.createNode()
            .setId("c")
            .setName("组件C")
            .setType(NodeTypeEnum.COMMON)
            .setClazz("com.yomahub.liteflow.test.builder.cmp1.CCmp")
            .build();
        LiteFlowNodeBuilder.createNode()
            .setId("d")
            .setName("组件D")
            .setType(NodeTypeEnum.COMMON)
            .setClazz("com.yomahub.liteflow.test.builder.cmp1.DCmp")
            .build();
        LiteFlowNodeBuilder.createNode()
            .setId("e")
            .setName("组件E")
            .setType(NodeTypeEnum.SWITCH)
            .setClazz("com.yomahub.liteflow.test.builder.cmp1.ECmp")
            .build();
        LiteFlowNodeBuilder.createNode()
            .setId("f")
            .setName("组件F")
            .setType(NodeTypeEnum.COMMON)
            .setClazz("com.yomahub.liteflow.test.builder.cmp1.FCmp")
            .build();
        LiteFlowNodeBuilder.createNode()
            .setId("g")
            .setName("组件G")
            .setType(NodeTypeEnum.COMMON)
            .setClazz("com.yomahub.liteflow.test.builder.cmp1.GCmp")
            .build();
        // 创建节点后,创建chain链路
        LiteFlowChainELBuilder.createChain().setChainName("chain2").setEL("THEN(c, d)").build();
        // 创建链路
        LiteFlowChainELBuilder.createChain()
            .setChainName("chain1")
            .setEL("THEN(a, b, WHEN(SWITCH(e).to(f, g, chain2)))")
            .build();
        // 基于流程执行器执行链路1
        LiteflowResponse response = flowExecutor.execute2Resp("chain1");
        Assertions.assertTrue(response.isSuccess());
        Assertions.assertEquals("a[组件A]==>b[组件B]==>e[组件E]==>c[组件C]==>d[组件D]", response.getExecuteStepStr());
    }

flowExecutor.execute2Resp("chain1")这个方法是业务逻辑执行的核心方法。但是在此之前会执行一些的方法:

1)LiteFlowNodeBuilder创建a到g组件节点。从代码中可以看到节点信息最终会添加到FlowBus中,使用了FlowBus.addNode(this.node.getId(), this.node.getName(), this.node.getType(), this.node.getClazz())。

2)LiteFlowChainELBuilder.createChain()创建chain的过程build中可以看到最终将数据也添加到了Chain中之外,还将chain添加到了chainMap中。

3)完成后,通过流程执行器完成请求 flowExecutor.execute2Resp("chain1")。

根据debug的信息,可以看到LiteflowExecutorInit实现了InitializingBean,重写afterPropertiesSet方法,此时会对flowExecutor做一次初始化,执行初始化Cmp,对应ruleResource进行判断,如果LiteflowConfig不存在配置信息,则加载SPI中,通过类加载器获取,如果存在,则加载,同时放入到liteflowConfig中,否则进行返回。

也即此时执行单元测试基于 flowExecutor.execute2Resp("chain1")进行执行后续的逻辑,也即3)中的方法,也即在这里完成所有的主体逻辑。

主体的逻辑整体在:

com.yomahub.liteflow.core.FlowExecutor#doExecute

这个方法里面。

因此我们对3)进行着重查看和说明。

三、chain.execute(slotIndex)的实现

//获取chain,根据chainId获取
    Chain chain = null;
    try {
        chain = FlowBus.getChain(chainId);
        if (ObjectUtil.isNull(chain)) {
            String errorMsg = StrUtil.format("couldn't find chain with the id[{}]", chainId);
            throw new ChainNotFoundException(errorMsg);
        }
        // 执行chain,也即设置槽id 对应chainId
        chain.execute(slotIndex);
    }

1)从chain到node的过程

可以看到首先会拿到chain,因为之前我们在2)完成了chain数据的填充,将将chain数据放入到了chainMap中。因此此时必然可以拿到chain的信息,然后基于chain调用节点执行器执行操作chain.execute(slotIndex)。Condition执行condition操作。当前所在的ChainName 如果对于子流程来说,那这个就是子流程所在的Chain。可以看到此时的executeCondition会执行对应的condition对应的chain。这里以串行器为例子进行说明,因此此时会进入到ThenCondition中。可以看到ThenConditon的executeCondition中存在前置preCondition.execute(slotIndex)、具体的处理executableItem.execute(slotIndex)、finally处理finallyCondition.execute(slotIndex)。此时可以看到对应的方法有三个:chain、condition、node。可以看到此时会执行节点node操作,因为前两者已经执行过。

2)node执行逻辑

设置槽索引和引用节点。,如果当前的实例可以access,则获取节点执行器,然后执行节点执行器。来到我们的执行器入口方法com.yomahub.liteflow.flow.executor.NodeExecutor#execute。这个方法可以看到,分为前置、执行中、后置方法。作者想得非常的周到,留下了扩展。除此之外,作者还给我们设置了失败重试的方法。节点组件的核心方法com.yomahub.liteflow.core.NodeComponent#execute。

在这个方法里面,会创建cmpStep对象,然后设置tag、step的信息。然后执行前置、具体的业务逻辑处理self.process(),此时会业务系统的组件方法中,也即我们自己业务系统写的NodeComponent方法,执行完成会执行成功的回调方法,如果出现异常,则设置step信息,然后执行失败回调方法。最终进行后置方法设置时间消耗。将指标统计信息添加到monitorBus中。

3)执行顺序与test中的设置对应关系

也即从这里可以看到首先会执行chain.execute(slotIndex)->executableItem.execute(slotIndex)->NodeComponent#execute,也即先执行chain,然后chain到对应的condition,最终到对应的node。也即应证了上面设置的顺序。先节点,然后condition,最终到chain。

四、实现的逻辑,可以总结如下UML


参考:https://gitee.com/dromara/liteFlow

          https://liteflow.cc/


目录
相关文章
|
Java
liteflow规则引擎 执行Groovy脚本
liteflow规则引擎 执行Groovy脚本
357 0
|
JavaScript 前端开发 Java
liteflow规则引擎 执行Javascript脚本
liteflow规则引擎 执行Javascript脚本
350 1
|
存储 缓存 JavaScript
国内开源规则引擎牛起来
国内开源规则引擎牛起来
1307 0
|
存储 Java 测试技术
【通用行业开发部】阿里开源TransmittableThreadLocal使用经验记录
本文章主要记录我在一次业务优化中,使用线程池带来的子父线程值传递问题,及使用TransmittableThreadLocal来解决该问题的经验,并对TransmittableThreadLocal原理做些梳理。
|
缓存 JavaScript Java
常见java OOM异常分析排查思路分析
Java虚拟机(JVM)遇到内存不足时会抛出OutOfMemoryError(OOM)异常。常见OOM情况包括:1) **Java堆空间不足**:大量对象未被及时回收或内存泄漏;2) **线程栈空间不足**:递归过深或大量线程创建;3) **方法区溢出**:类信息过多,如CGLib代理类生成过多;4) **本机内存不足**:JNI调用消耗大量内存;5) **GC造成的内存不足**:频繁GC但效果不佳。解决方法包括调整JVM参数(如-Xmx、-Xss)、优化代码及使用高效垃圾回收器。
539 15
常见java OOM异常分析排查思路分析
|
5月前
|
消息中间件 Java Kafka
Spring Boot整合kafka
本文简要记录了Spring Boot与Kafka的整合过程。首先通过Docker搭建Kafka环境,包括Zookeeper和Kafka服务的配置文件。接着引入Spring Kafka依赖,并在`application.properties`中配置生产者和消费者参数。随后创建Kafka配置类,定义Topic及重试机制。最后实现生产者发送消息和消费者监听消息的功能,支持手动ACK确认。此方案适用于快速构建基于Spring Boot的Kafka消息系统。
1001 7
|
7月前
|
人工智能 自然语言处理 搜索推荐
飞算 JavaAI:开发界的 “AI 教练”,助你飞速成长!
飞算JavaAI如同开发者的“AI教练”,通过深度洞察需求、精准绘制开发蓝图,以自然语言解析需求,自动生成接口和表结构,简化业务理解。其全方位开发指导功能,细致设计每个细节,帮助开发者梳理业务规则与数据流程,提高开发效率。全程智能辅助则自动输出完整工程源码,涵盖配置类文件、Java代码及测试资源,让开发者专注于优化业务逻辑和实现个性化功能。无论是新手还是资深开发者,飞算JavaAI都是不可或缺的得力伙伴,助力快速成长与技术突破。
|
XML Java 决策智能
拥抱智能决策新纪元!Spring Boot携手LiteFlow规则引擎,让复杂业务处理如丝般顺滑,引领技术潮流!
【8月更文挑战第29天】LiteFlow是一款专为Java应用设计的轻量级规则引擎,支持条件、循环、分支等多种规则类型,具有组件化设计和高度可扩展性。通过自定义规则和事件监听,它可以显著提升代码的可维护性和可重用性。本文将详细介绍如何在Spring Boot项目中整合LiteFlow,并通过实际案例演示其强大功能。主要步骤包括:添加依赖、配置参数、定义组件及流程,并通过API触发执行。借助LiteFlow,复杂业务逻辑处理变得更加灵活高效。
577 0
|
Java API
QLExpress功能清单
QLExpress从一开始就是从复杂的阿里电商业务系统出发,并且不断完善的脚本语言解析引擎框架,在不追求java语法的完整性的前提下(比如异常处理,foreach循环,lambda表达式,这些都是groovy是强项),定制了很多普遍存在的业务需求解决方案(比如变量解析,spring打通,函数封装,操作符定制,宏替换),同时在高性能、高并发、线程安全等方面也下足了功夫,久经考验。
21555 1
|
Java uml
liteflow学习二
liteflow学习二
513 0

热门文章

最新文章