规则引擎LIfeflow 用法

规则引擎

规则引擎通常是嵌入在应用程序组件中的,实现了将业务决策从应用程序代码中分离出来,并使用预定义的语义模块编写业务决策。接受数据输入,解释业务规则,并根据业务规则做出业务决策。简单来说就是,规则引擎主要解决易变逻辑和业务耦合的问题,规则驱动逻辑。以前项目内写死在代码里的逻辑用规则引擎可以提出来,随时热变更。

Drools VS LiteFlow

总的来说,两款框架都能用脚本来定义逻辑片段,在定义逻辑片段层面,Drools使用的是自研语法,LiteFlow使用的是插件式的Groovy,其实个人觉得Groovy更接近java语法,你甚至于可以在其中定义类和方法。Drools在高级应用中,也可以用规则定义方法,但是我觉得并不那么自然。

LiteFlow最大的特点是除了定义逻辑片段外,还可以进行全局组件(组件的边界:最小可复用的逻辑单元)的编排。而这正是LiteFlow称之为编排式规则引擎的由来。使用简单的编排语法可以设计出复杂的逻辑流。支持java和脚本混编。

Liteflow介绍

  • 它是一个编排式的规则引擎框架,组件编排,帮助解耦业务代码,让每一个业务片段都是一个组件。
    利用LiteFlow,你可以将瀑布流式的代码,转变成以组件为核心概念的代码结构,这种结构的好处是可以任意编排,组件与组件之间是解耦的,组件可以用脚本来定义,组件之间的流转全靠规则来驱动。LiteFlow拥有开源规则引擎最为简单的DSL语法。组件可实时热更替,也可以给编排好的逻辑流里实时增加一个组件,从而改变你的业务逻辑。
  • LiteFlow支持把编排规则和脚本放在数据库,注册中心中,还有可以任意扩展的接口,方便你定制。

LiteFlow不适用于哪些场景
LiteFlow只做基于逻辑的流转,而不做基于角色任务的流转。如果你想做基于角色任务的流转的工作流,推荐使用
LiteFlow适用于哪些场景
LiteFlow适用于拥有复杂逻辑的业务,比如说价格引擎,下单流程等,这些业务往往都拥有很多步骤,这些步骤完全可以按照业务粒度拆分成一个个独立的组件,进行装配复用变更。

元数据管理
https://liteflow.cc/pages/7cb165/

组件之间的参数传递

上下文对象

Liteflow用法 -- 需求联想法

某些规则可以通过脚本的方式修改,并且热更新 。 规则里面用的参数 上下文参数需要通过一定的额方式注入
规则(组件)和规则(组件)可以灵活编排,也可以支持热更新 。 通过一个chain(规则链),支持OR,AND,或者任意满足就结束等。

规则的计算结果,可以在JAVA代码里面获取。 规则的计算结果是什么类型? 除了复杂对象类型外,其他都可以。 ????

该框架文档不是很齐全,要灵活使用需要把 NodeComponent几个子类源码熟读。
不同版本用法差异很大,需要甄别

用法

WHEN 并行编排

使用 NodeComponent 自定义组件。 实现process()方法

THEN 串行编排

使用 NodeComponent 自定义组件。 实现process()方法

IF 判断语句

条件判断的组件继承 NodeIfComponent必须重新processIf()方法。 当processIf()返回true,往下走流程 。 不能重写process()方法(参考NodeIfComponent 源码)
以下例子:x 的组件继承NodeIfComponent
a,b,c组件继承 NodeComponent

 THEN(
        IF(x, a, b),
        c
        );

组件之间的上下文传递

1. 使用默认上下文(Context)

LiteFlow 默认提供了一个 Context 对象,可以在组件之间共享数据。

示例代码:

// 定义组件 A,设置变量
@LiteflowComponent("a")
public class A extends NodeComponent {
    @Override
    public void process() {
        // 设置变量到上下文
        this.getContext().setData("key", "value");
    }
}

// 定义组件 B,读取变量
@LiteflowComponent("b")
public class B extends NodeComponent {
    @Override
    public void process() {
        // 从上下文获取变量
        String value = this.getContext().getData("key");
        System.out.println(value); // 输出 "value"
    }
}

2. 自定义上下文对象

如果需要传递复杂对象,可以自定义一个上下文类(继承 Context)。

步骤:

  1. 定义自定义上下文类

    public class MyContext extends Context {
        private String data;
        private Map<String, Object> params = new HashMap<>();
    
        // Getter/Setter
        public String getData() { return data; }
        public void setData(String data) { this.data = data; }
    
        public void putParam(String key, Object value) {
            params.put(key, value);
        }
        public Object getParam(String key) {
            return params.get(key);
        }
    }
    
  2. 在组件中使用自定义上下文

    @LiteflowComponent("a")
    public class A extends NodeComponent {
        @Override
        public void process() {
            MyContext context = this.getContextBean(MyContext.class);
            context.setData("hello");
            context.putParam("user", "LiteFlow");
        }
    }
    
    @LiteflowComponent("b")
    public class B extends NodeComponent {
        @Override
        public void process() {
            MyContext context = this.getContextBean(MyContext.class);
            String data = context.getData(); // "hello"
            String user = (String) context.getParam("user"); // "LiteFlow"
        }
    }
    
  3. 在流程声明中初始化上下文

    <!-- 在流程定义中指定上下文类 -->
    <chain name="chain1">
        <then value="a, b"/>
    </chain>
    

3. 通过流程初始参数传递

在流程启动时,可以通过 LiteflowResponse 传递初始参数,并在组件中获取。

示例:

// 启动流程时传入参数
LiteflowResponse response = FlowExecutor.execute2Resp("chain1", "初始参数", MyContext.class);

// 在组件中获取参数
@LiteflowComponent("a")
public class A extends NodeComponent {
    @Override
    public void process() {
        String arg = this.getRequestData(); // 获取到 "初始参数"
    }
}

4. 通过 Node 的 slot 参数(旧版本兼容)

在 LiteFlow 旧版本中,使用 slot 作为共享数据槽,但新版本推荐使用上下文对象。

示例(兼容旧版):

// 组件 A 设置数据
this.getSlot().setData("key", "value");

// 组件 B 获取数据
String value = this.getSlot().getData("key");

关键注意事项

  1. 上下文隔离性:每个请求的上下文是独立的,天然支持并发。
  2. 线程安全:无需担心多线程问题,LiteFlow 保证上下文的线程隔离。
  3. 类型明确性:自定义上下文时,建议通过明确的 getter/setter 操作数据,避免直接暴露字段。

领域对象

Slot vs Context

LiteFlow 中,Slot 是旧版本(如 1.x)中用于组件间共享数据的核心概念,但在新版本(2.x+)中已被 Context(上下文) 替代。以下是详细解释:


1. Slot 的原始定义(旧版本)

  • 作用
    Slot 是流程执行过程中用于存储数据的共享容器,所有组件(Node)可以读写其中的数据。
  • 特点
    • 全局共享:一个流程实例对应一个 Slot,所有组件通过 this.getSlot() 访问。
    • 无类型约束:数据以 Map<String, Object> 形式存储,需手动处理类型转换。
    • 线程隔离:每个请求的 Slot 独立,天然支持并发。

旧版本代码示例

// 组件A设置数据
public class A extends NodeComponent {
    @Override
    public void process() {
        this.getSlot().setData("user", "Alice");
        this.getSlot().setData("count", 100);
    }
}

// 组件B读取数据
public class B extends NodeComponent {
    @Override
    public void process() {
        String user = (String) this.getSlot().getData("user");
        int count = (int) this.getSlot().getData("count");
    }
}

2. 为何被 Context 取代?

Slot 的缺点推动了新版本设计改进:

  1. 类型不安全:数据存取需强制类型转换,易引发 ClassCastException
  2. 结构不清晰:所有数据混在一个 Map 中,难以维护。
  3. 扩展性差:无法为不同业务场景定制数据结构。

3. 新版本的 Context(上下文)

LiteFlow 2.x 开始,Context 替代了 Slot,提供更安全、灵活的数据传递机制:

  • 类型安全:通过自定义上下文类(如 OrderContextUserContext)明确字段和类型。
  • 多上下文支持:一个流程可同时携带多个不同类型的上下文。
  • 结构清晰:不同业务数据分离到独立上下文中。

新版本代码示例

// 自定义上下文类
public class OrderContext extends Context {
    private String orderId;
    private int amount;

    // Getter/Setter
}

// 组件A设置数据
@LiteflowComponent("a")
public class A extends NodeComponent {
    @Override
    public void process() {
        OrderContext context = this.getContextBean(OrderContext.class);
        context.setOrderId("ORDER_123");
        context.setAmount(200);
    }
}

// 组件B读取数据
@LiteflowComponent("b")
public class B extends NodeComponent {
    @Override
    public void process() {
        OrderContext context = this.getContextBean(OrderContext.class);
        String orderId = context.getOrderId(); // 无需强制转换
    }
}

4. 新旧版本对比

特性 Slot(旧版本) Context(新版本)
数据存储 单一 Map,无类型约束 多上下文对象,类型安全
数据隔离 一个流程一个 Slot 可同时存在多个上下文(如 OrderContext, UserContext
代码可维护性 低(数据混杂) 高(业务数据分离)
扩展性 强(支持自定义上下文类)

5. 迁移建议

  1. 新项目:直接使用 Context,无需关注 Slot
  2. 旧项目升级
    • this.getSlot().setData() 替换为自定义上下文类的 setter 方法。
    • 使用 getContextBean(Class) 替代 getSlot().getData()
    • 删除旧版 Slot 相关代码。

总结

  • Slot 是 LiteFlow 旧版本的数据共享机制,已过时。
  • Context 是新版本推荐的解决方案,提供类型安全和结构化数据管理。
  • 如果仍在旧版本中使用 Slot,建议尽快升级到 2.x+ 并迁移到 Context

参考资料

https://blog.csdn.net/WXF_Sir/article/details/144129776
官方文档
https://liteflow.cc/pages/5816c5/#liteflow框架的优势

posted @ 2025-02-25 18:01  向着朝阳  阅读(457)  评论(0)    收藏  举报