因爲在項目要用到Drools,所以下面寫了一個簡單的例子學習入門。
一、Drools簡介:
JBoss Rules 的前身是Codehaus的一個開源項目叫 Drools。最近被納入JBoss門下,更名爲JBoss Rules,成爲了JBoss應用服務器的規則引擎。
Drools 是爲 Java 量身定製的基於Charles Forgy的RETE算法的規則引擎的實現。具有了OO接口的RETE,使得商業規則有了更自然的表達。
Drools 的用 XML 的<Conditons>、<Consequence> 節點表達If–Then句式,而裏面可以嵌入上述語言的代碼作爲判斷語句和執行語句。
其中 Java 代碼會使用Antlr進行解釋,而 Groovy 和 Python 本身就是腳本語言,可以直接調用。
Drools 的聰明之處在於,用 XML 節點來規範 If–Then 句式和事實的定義,使引擎幹起活來很舒服。
而使用 Java,Groovy等原生語言來做判斷和執行語句,讓程序員很容易過渡、移植,學習曲線很低。
二、幾個重要概念
- 事實(Fact):對象之間及對象屬性之間的關係
- 規則(rule):是由條件和結論構成的推理語句,一般表示爲if...Then。一個規則的if部分稱爲LHS,then部分稱爲RHS。
- 模式(module):就是指IF語句的條件。這裏IF條件可能是有幾個更小的條件組成的大條件。模式就是指的不能在繼續分割下去的最小的原子條件。
三、.drl 文件內容
package com.rules
import com.drools.model.Person
import com.drools.model.Goods
rule "test-drools-older than 60"
when
no-loop true
lock-on-active true
salience 1
$Goods : Goods(person.age > 60)
then
$Goods.setDiscount(80);
System.out.println("test-drools-older than 60 " + $Goods.getPerson().getAge());
end
- package 與Java語言類似,drl的頭部需要有package和import的聲明,package不必和物理路徑一致。
- import 導出java Bean的完整路徑,也可以將Java靜態方法導入調用。
- rule 規則名稱,需要保持唯一 件,可以無限次執行。
- no-loop 定義當前的規則是否不允許多次循環執行,默認是 false,也就是當前的規則只要滿足條件,可以無限次執行。
- lock-on-active 將lock-on-active屬性的值設置爲true,可避免因某些Fact對象被修改而使已經執行過的規則再次被激活執行。
- salience 用來設置規則執行的優先級,salience 屬性的值是一個數字,數字越大執行優先級越高, 同時它的值可以是一個負數。默認情況下,規則的 salience 默認值爲 0。如果不設置規則的 salience 屬性,那麼執行順序是隨機的。
- when 條件語句,就是當到達什麼條件的時候
- then 根據條件的結果,來執行什麼動作
- end 規則結束
這個規則文件就是描述了,當符合什麼條件的時候,應該去做什麼事情,每當規則有變動的時候,我們只需要修改規則文件,然後重新加載即可生效。
四、kmodule.xml
kmodule.xml的作用就是告訴代碼規則文件drl在哪裏,在drools中這個文件就是kmodule.xml,放置到resources/META-INF目錄下。kmodule.xml內容如下:
<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
<kbase name="rules">
<ksession name="all-rules"/>
</kbase>
</kmodule>
以下對配置說明進行簡單說明:
- Kmodule 中可以包含一個到多個 kbase,分別對應 drl 的規則文件。
- Kbase 需要一個唯一的 name,可以取任意字符串。
- packages 爲drl文件所在resource目錄下的路徑。注意區分drl文件中的package與此處的package不一定相同。多個包用逗號分隔。默認情況下會掃描 resources目錄下所有(包含子目錄)規則文件。
- kbase的default屬性,標示當前KieBase是不是默認的,如果是默認的則不用名稱
就可以查找到該 KieBase,但每個 module 最多只能有一個默認 KieBase。- kbase 下面可以有一個或多個 ksession,ksession 的 name 屬性必須設置,且必須唯一。
五、下面是一個簡單的入門例子
1、首先項目的結構如下
2、引入drools的依賴
<dependencies>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>7.7.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>7.7.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-templates</artifactId>
<version>7.7.0.Final</version>
</dependency>
</dependencies>
3、創建一個xml,注意一定要放在META-INF文件夾下,drools會自動解析它
<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
<kbase name="rules">
<ksession name="all-rules"/>
</kbase>
</kmodule>
4、創建實體Goods和Person
5、創建規則droolsRules.drl
package com.rules
import com.drools.model.Person
import com.drools.model.Goods
rule "test-drools-older than 60"
when
$Goods : Goods(person.age > 60)
then
$Goods.setDiscount(80);
System.out.println("test-drools-older than 60 " + $Goods.getPerson().getAge());
end
rule "test-drools-other"
when
$Goods : Goods(person.age <= 60)
then
$Goods.setDiscount(70);
System.out.println("test-drools-other " + $Goods.getPerson().getAge());
end
6、測試類
public class DroolsTest {
public static void main(String[] args) {
//獲取一個實例
KieServices kieServices = KieServices.Factory.get();
//默認去讀取配置文件
KieContainer kieContainer = kieServices.getKieClasspathContainer();
//根據這個名詞去獲取kieSession
KieSession kieSession = kieContainer.newKieSession("all-rules");
Person p1 = new Person();
p1.setAge(30);
p1.setName("Tom");
Goods g1 = new Goods();
g1.setPerson(p1);
Person p2 = new Person();
p2.setAge(70);
p2.setName("Joy");
Goods g2 = new Goods();
g2.setPerson(p2);
//將person實例放入session中
kieSession.insert(g1);
kieSession.insert(g2);
//開始執行規則,並獲取執行了多少條規則
int count = kieSession.fireAllRules();
//關閉session
kieSession.dispose();
System.out.println("Fire " + count + " rule(s)!");
System.out.println("The discount of g1 is " + g1.getDiscount() + "%");
System.out.println("The discount of g2 is " + g2.getDiscount() + "%");
}
}
7、運行結果
test-drools-older than 60 70
test-drools-other 30
Fire 2 rule(s)!
The discount of g1 is 70%
The discount of g2 is 80%