规则引擎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)。
步骤:
-
定义自定义上下文类:
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); } } -
在组件中使用自定义上下文:
@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" } } -
在流程声明中初始化上下文:
<!-- 在流程定义中指定上下文类 --> <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");
关键注意事项
- 上下文隔离性:每个请求的上下文是独立的,天然支持并发。
- 线程安全:无需担心多线程问题,LiteFlow 保证上下文的线程隔离。
- 类型明确性:自定义上下文时,建议通过明确的
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 的缺点推动了新版本设计改进:
- 类型不安全:数据存取需强制类型转换,易引发
ClassCastException。 - 结构不清晰:所有数据混在一个
Map中,难以维护。 - 扩展性差:无法为不同业务场景定制数据结构。
3. 新版本的 Context(上下文)
从 LiteFlow 2.x 开始,Context 替代了 Slot,提供更安全、灵活的数据传递机制:
- 类型安全:通过自定义上下文类(如
OrderContext、UserContext)明确字段和类型。 - 多上下文支持:一个流程可同时携带多个不同类型的上下文。
- 结构清晰:不同业务数据分离到独立上下文中。
新版本代码示例:
// 自定义上下文类
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. 迁移建议
- 新项目:直接使用
Context,无需关注Slot。 - 旧项目升级:
- 将
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框架的优势

浙公网安备 33010602011771号