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