drools引擎使用
官网介绍
一、底层原理
-
ReteOO 网络
• 本质是一张“有向无环图”,节点类型:
– Root / ObjectTypeNode:按 Java 类型分发事实
– AlphaNode:单对象约束(age > 18)
– BetaNode(Join / Not / Exists):多对象关联(o.customer == c)
– TerminalNode:规则完全匹配,生成 Activation 放进 Agenda
• 优势:用空间换时间,缓存中间结果,避免重复计算 。 -
工作内存(Working Memory)
• 存放所有插入的 Fact(Java Bean),内部用 Map<Class, ObjectStore> 维护。 -
议程(Agenda)
• 存放“可触发”的 Activation;支持 salience、agenda-group、ruleflow-group 等冲突解决策略。 -
推理循环
insert / update / delete → 网络传播 → Agenda 新增/修改 Activation → fireAllRules → 执行 RHS 。
——————————————————
二、使用方式(最简三步)
- 引入 Maven
<dependency><groupId>org.drools</groupId><artifactId>drools-core</artifactId><version>8.44.0.Final</version>
</dependency>
- 规则文件
src/main/resources/rules/order.drl
package rules
import com.demo.Orderrule "large-order-discount"
when$o : Order(amount > 100)
then$o.setDiscount(0.9); // 打9折System.out.println("Large order discount applied");
end
- Java 启动类
// 1. 创建Kie容器
KieServices kieServices = KieServices.Factory.get();
KieContainer kContainer = kieServices.getKieClasspathContainer();// 2. 创建会话
KieSession kieSession = kContainer.newKieSession("ksession-rules");// 3. 插入事实
kieSession.insert(new Person("John", 25, "male"));// 4. 执行规则
kieSession.fireAllRules();// 5. 释放资源
kieSession.dispose();
——————————————————
三、源码级要点(8.x 分支)
-
入口
•KieServices.Factory.get()
→KieContainerImpl
→KieBaseImpl
完成 drl 编译。 -
规则编译
•DrlParser
把规则文本 → AST →PackageDescr
•KnowledgeBuilderImpl
调用ReteCompiler
构建网络,生成RuleImpl
和Rete
对象 。 -
事实插入链路(调试可直接打断点)
FactHandle handle = kSession.insert(obj);-> StatefulKnowledgeSessionImpl.insert()-> ObjectStore.add()-> propagate()-> ReteOOWorkingMemory.update()-> ObjectTypeNode.assertObject()-> AlphaNode.assertObject()-> BetaNode.assertObject()-> TerminalNode.assertObject()-> Agenda.addActivation()
- 规则执行
•DefaultAgenda.fireNextItem()
取出 Activation →RuleExecutor.evaluate()
→ 执行 RHS 对应的ConsequenceGenerator
生成的字节码。
——————————————————
四、完整可运行 Demo(Spring Boot 可直接启动)
目录结构
src
└─ main├─ java│ └─ com.demo│ ├─ Order.java│ └─ DroolsApp.java└─ resources├─ rules/order.drl└─ META-INF/kmodule.xml
- Order.java
@Data
public class Order {private int amount;private double discount = 1.0;public double getFinalAmount() {return amount * discount;}
}
- kmodule.xml
<kmodule xmlns="http://www.drools.org/xsd/kmodule"><kbase name="rules" packages="rules"><ksession name="ksession-rules"/></kbase>
</kmodule>
- DroolsApp.java
@SpringBootApplication
public class DroolsApp implements CommandLineRunner {public static void main(String[] args) {SpringApplication.run(DroolsApp.class, args);}@Overridepublic void run(String... args) {KieServices ks = KieServices.Factory.get();KieContainer kc = ks.getKieClasspathContainer();KieSession kSession = kc.newKieSession("ksession-rules");Order order = new Order();order.setAmount(150);kSession.insert(order);kSession.fireAllRules();kSession.dispose();System.out.println("amount=" + order.getAmount()+ ", discount=" + order.getDiscount()+ ", finalAmount=" + order.getFinalAmount());}
}
运行结果
Large order discount applied
amount=150, discount=0.9, finalAmount=135.0