4. 第一个Champion规则:创建最简单的规则文件(.drl格式)、规则语法结构(rule/condition/action)、加载规则并执行
本章将带领你从零创建第一个Champion规则文件,理解.drl格式的核心语法结构,并通过Python代码加载规则并执行。这是后续所有规则开发的基础,请务必动手完成每一步。
4.1 .drl规则文件格式
.drl(Drools Rule Language)是Drools规则引擎的标准规则文件格式,本质上是纯文本文件,使用.drl作为扩展名。一个最简单的.drl文件包含以下基本要素:
| 要素 | 说明 | 示例 |
|---|---|---|
| package | 规则包声明,用于逻辑分组(可选但推荐) | package com.champion.rules |
| import | 导入Java/Python类或数据类型 | import com.champion.model.Order |
| rule | 规则定义块,包含名称、条件、动作 | rule "HelloWorld" |
| when | 条件部分(LHS),匹配事实 | when $o: Order(amount > 100) |
| then | 动作部分(RHS),执行逻辑 | then System.out.println("大额订单"); |
💡 提示:在Champion实验环境中,.drl文件使用UTF-8编码,文件名建议使用英文小写+下划线,例如
first_rule.drl。
4.2 规则语法结构:rule / condition / action
每个规则由三个核心部分组成,遵循“当条件满足时执行动作”的范式:
- rule 名称:规则唯一标识,用双引号包裹,如
rule "CheckDiscount" - when(条件):定义触发规则的条件表达式,支持逻辑运算符(&&、||、!)和模式匹配
- then(动作):条件满足时执行的代码块,可以修改事实、输出日志、调用外部服务等
下面是一个完整的.drl文件示例,包含一个简单的规则:
package champion.demo
// 导入Python对象(在Champion中通过桥接层支持)
import champion.model.Person
rule "AdultCheck"
when
$p: Person(age >= 18)
then
System.out.println($p.getName() + " 是成年人");
$p.setAdult(true);
end
📌 关键点:
- 规则以
rule "名称"开始,以end结束 when和then之间不要有空行(语法要求)- 条件中的变量绑定使用
$变量名:格式,如$p: Person(...) - 动作部分支持Java语法(Champion引擎内部基于Java实现)
4.3 加载规则并执行
在Champion实验环境中,我们使用Python代码加载.drl文件、创建规则引擎会话并执行规则。以下是完整的操作流程:
- 准备.drl文件:将规则文件放置在项目目录(如
rules/文件夹) - 初始化规则引擎:创建KieContainer并读取规则库
- 插入事实对象:将需要匹配的数据对象插入工作内存
- 触发规则:调用
fireAllRules()执行匹配的规则 - 获取结果:从事实对象中读取规则执行后的状态变化
下面是一个完整的Python执行脚本示例:
# champion_execute.py
from champion import KieServices, KieHelper
from champion.model import Person
# 1. 加载规则文件
ks = KieServices.Factory.get()
kcontainer = ks.newKieContainer(
ks.newReleaseId("champion", "demo-rules", "1.0.0")
)
# 或者使用KieHelper直接加载.drl文件
kh = KieHelper()
kh.addResource("rules/first_rule.drl")
kbase = kh.build()
ksession = kbase.newKieSession()
# 2. 创建事实对象
person = Person(name="张三", age=25, adult=False)
# 3. 插入事实
ksession.insert(person)
# 4. 执行规则
ksession.fireAllRules()
# 5. 输出结果
print(f"姓名: {person.getName()}")
print(f"年龄: {person.getAge()}")
print(f"是否成年人: {person.isAdult()}")
# 6. 释放资源
ksession.dispose()
⚠️ 常见错误:
- 忘记调用
dispose()导致内存泄漏 - 事实对象未正确设置getter/setter方法
- .drl文件中类名或包名与Python模型不一致
4.4 规则执行流程SVG图
下图展示了从加载规则文件到执行完成的完整数据流:
4.5 规则语法对比表
为了帮助你快速区分.drl规则中的不同语法元素,下表列出了常见模式及其含义:
| 语法模式 | 含义 | 示例 |
|---|---|---|
$var: ClassName( field == value ) |
绑定变量并匹配字段等于某值 | $o: Order( status == "NEW" ) |
$var: ClassName( field > value ) |
匹配字段大于某值 | $p: Person( age > 18 ) |
not ClassName( ... ) |
不存在匹配的事实 | not Person( name == "admin" ) |
exists ClassName( ... ) |
至少存在一个匹配的事实 | exists Order( amount > 1000 ) |
eval( 表达式 ) |
执行任意布尔表达式 | eval( $p.getAge() >= 18 ) |
4.6 动手实验:创建并运行第一个规则
按照以下步骤完成你的第一个Champion规则实验:
- 创建项目结构:在
champion_workspace/下新建rules/文件夹 - 编写规则文件:在
rules/中创建hello_champion.drl,内容如下:
package champion.hello
rule "SayHello"
when
$msg: String(this == "champion")
then
System.out.println("Hello, Champion Rule Engine!");
end
- 编写Python执行脚本:创建
run_hello.py:
from champion import KieHelper
kh = KieHelper()
kh.addResource("rules/hello_champion.drl")
kbase = kh.build()
ksession = kbase.newKieSession()
ksession.insert("champion")
ksession.fireAllRules()
ksession.dispose()
- 运行脚本:在终端执行
python run_hello.py,控制台应输出Hello, Champion Rule Engine!
✅ 验证成功:如果看到上述输出,说明你的第一个Champion规则已经成功加载并执行!这是你掌握规则引擎的里程碑。
4.7 规则文件与执行架构SVG图
下图展示了Champion规则引擎的组件架构及数据流向:
4.8 常见问题与排错
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 规则未触发 | 条件不匹配或事实未插入 | 检查 insert() 是否调用,条件表达式是否正确 |
| ClassNotFoundException | 模型类未导入或路径错误 | 确认 import 语句中的类名与Python模型一致 |
| 语法错误 | .drl文件格式错误 | 检查 when/then 缩进,确保 end 存在 |
| 内存泄漏 | 未调用 dispose() |
在 finally 块中释放KieSession |
📘 本章小结:
- .drl文件是规则引擎的规则定义文件,包含package、import、rule等要素
- 规则结构为
rule "名称" when 条件 then 动作 end - Python通过KieHelper加载.drl文件,创建KieSession,插入事实并调用fireAllRules()
- 规则执行流程:加载→编译→匹配→触发→输出