Drools 规则引擎实战:原理、规则语法、数据库动态规则与企业级玩法
什么是 Drools
Drools 是一个基于 Java 的规则引擎(Rule Engine)。
它的核心目标:
text
将业务规则从 Java 代码中解耦出来。
例如:
传统代码:
java
if(orderAmount > 1000 && vip){
discount += 200;
}
随着业务增长:
- VIP规则
- 新人规则
- 节日活动
- 门店活动
- 满减
- 风控
- 审核
最终会形成:
text
if else 地狱
Drools 的核心思想:
text
业务规则 ≠ Java代码
而是:
text
规则 = 可动态配置的业务决策
Drools 的核心能力
Drools 最强的地方不是:
text
if 判断
而是:
规则推理
例如:
text
规则A:
VIP用户增加200优惠
规则B:
新人增加50优惠
规则C:
优惠超过300需要审核
规则 C 并不知道:
- 优惠来自 VIP
- 还是来自 新人
- 还是来自 活动
它只关心:
text
最终事实
这就是:
基于事实(Fact)的推理
Drools 核心概念
| 概念 | 说明 |
|---|---|
| Fact | 事实对象(Java Bean) |
| Rule | 规则 |
| Working Memory | 工作内存 |
| KieSession | 规则运行会话 |
| Agenda | 待执行规则队列 |
| Rete Network | 底层推理网络 |
Drools 工作流程
第一步:插入事实对象
java
session.insert(order);
session.insert(user);
session.insert(result);
这些对象:
会进入:
Working Memory
第二步:规则匹配
Drools 会自动匹配:
drools
Order(amount > 1000)
User(vip == true)
第三步:触发规则
drools
then
$r.addDiscount(200);
第四步:规则联动
另一个规则:
drools
DecisionResult(totalDiscount > 300)
会再次自动触发。
Drools 规则语法(DRL)
Drools 使用:
text
.drl
规则文件。
一个完整规则
drools
package rules
import com.demo.Order
import com.demo.User
import com.demo.DecisionResult
rule "vip discount"
when
Order(amount > 1000)
User(vip == true)
$r : DecisionResult()
then
$r.addDiscount(200);
System.out.println("触发VIP优惠");
end
DRL 语法结构
| 语法 | 说明 |
|---|---|
| package | 包名 |
| import | 导入Java类 |
| rule | 规则名称 |
| when | 条件 |
| then | 动作 |
| end | 规则结束 |
条件部分(when)
例如:
drools
Order(amount > 1000)
等价于:
java
order.getAmount() > 1000
多条件
drools
Order(amount > 1000)
User(vip == true)
表示:
text
同时满足
变量绑定
drools
$r : DecisionResult()
表示:
text
把 DecisionResult 绑定为变量 $r
后面:
drools
$r.addDiscount(200);
即可直接调用。
then 动作部分
drools
then
$r.addDiscount(200);
本质:
是:
java
result.addDiscount(200);
Drools:
底层仍然是 Java 对象操作。
一个完整营销规则示例
order.drl
drools
package rules
import com.demo.Order
import com.demo.User
import com.demo.DecisionResult
rule "vip discount"
when
Order(amount > 1000)
User(vip == true)
$r : DecisionResult()
then
$r.addDiscount(200);
System.out.println("触发:VIP优惠");
end
rule "new user discount"
when
User(newUser == true)
$r : DecisionResult()
then
$r.addDiscount(50);
System.out.println("触发:新人优惠");
end
rule "big order point"
when
Order(amount > 5000)
$r : DecisionResult()
then
$r.addPoint(100);
System.out.println("触发:大额积分");
end
rule "need audit"
when
$r : DecisionResult(totalDiscount > 300)
then
$r.setNeedAudit(true);
System.out.println("触发:人工审核");
end
如何与数据库结合
企业里:
几乎不会把规则写死:
text
rules/*.drl
因为:
运营会频繁修改规则。
数据库设计
rule_definition
sql
CREATE TABLE rule_definition
(
id BIGINT PRIMARY KEY,
rule_code VARCHAR(50),
rule_name VARCHAR(200),
drl_content TEXT,
status INT,
version_no INT,
tenant_id BIGINT,
add_date DATETIME
);
数据库存储规则
drools
rule "vip discount"
when
Order(amount > 1000)
then
...
end
直接存:
text
TEXT
即可。
动态加载规则
从数据库读取
java
String drl = ruleMapper.getRuleContent("vip_rule");
动态编译
java
KieServices ks = KieServices.Factory.get();
KieFileSystem kfs = ks.newKieFileSystem();
kfs.write(
"src/main/resources/rules/vip.drl",
drl
);
KieBuilder kb = ks.newKieBuilder(kfs);
kb.buildAll();
创建 KieSession
java
KieContainer kc = ks.newKieContainer(
ks.getRepository().getDefaultReleaseId()
);
KieSession session = kc.newKieSession();
执行规则
java
session.insert(order);
session.insert(user);
session.insert(result);
session.fireAllRules();
常用高级语法
salience(优先级)
drools
rule "vip"
salience 100
数字越大:
越先执行。
no-loop
防止死循环。
drools
rule "test"
no-loop true
update()
更新事实对象。
drools
update($r);
会重新触发规则匹配。
agenda-group
规则分组。
drools
agenda-group "marketing"
企业使用中的真实问题
Drools:
虽然强大。
但:
也有很多问题。
- 启动重
- 内存占用高
- 调试困难
- 规则冲突难排查
- 热更新复杂
- 学习曲线高
ERP/收银系统中的最佳实践
真实企业:
通常:
核心交易逻辑
使用:
text
Java硬编码
保证:
- 性能
- 稳定
- 可控
动态营销规则
使用:
text
Drools
保证:
- 灵活
- 动态配置
- 运营可控
- 热更新
总结
Drools 本质:
不是:
text
替代 Java
而是:
在 Java 之上构建业务规则推理层
它真正的价值:
是:
业务规则动态化
以及: