Drools 規則學習java
在 Drools 當中,一個標準的規則文件就是一個以「.drl」結尾的文本文件,因爲它是一
個標準的文本文件,因此能夠經過一些記事本工具對其進行打開、查看和編輯。規則是放在
規則文件當中的,一個規則文件能夠存放多個規則,除此以外,在規則文件當中還能夠存放
用戶自定義的函數、數據對象及自定義查詢等相關在規則當中可能會用到的一些對象。
文件結構圖以下:
package
imports
globals
functions
queries
rules
.....正則表達式
對於一個規則文件而言,首先聲明 package 是必須的,除 package 以外,其它對象在規
則文件中的順序是任意的,也就是說在規則文件當中必需要有一個 package 聲明,同時
package 聲明必需要放在規則文件的第一行。一個規則一般包括三個部分:屬性部分(attribute) 、條件
部分(LHS)和結果部分(RHS) 一個標準規則的結構以下:
rule "name"
attributes
when
LHS
then
RHS
end函數
1.在 LHS 當中,能夠包含 0~n 個條件,若是 LHS 部分沒空的話,那麼引擎會自動添加一個 eval(true)的條件,因爲該條件老是返回 true,因此 LHS 爲空的規則老是返回 true
2.在這兩個pattern沒有符號鏈接, 在Drools當中在 pattern 中沒有鏈接符號,那麼就用 and 來做爲默認鏈接,因此在該規則的 LHS 部分中兩個 pattern 只有都知足了纔會返回 true。默認狀況下,每行能夠用「;」來做爲結束符(和Java 的結束同樣) ,固然行尾也能夠不加「;」結尾。工具
條件部分
1.約束鏈接
對於對象內部的多個約束的鏈接,能夠採用「&&」 (and) 、 「||」(or)和「,」(and)來實現
示例代碼:
rule "rule1"
when
Customer(age>20 || gender==’male’&& city==’sh’)
then
<action>…
End
2.比較操做符
在 Drools當中共提供了十二種類型的比較操做符, 分別是: >、 >=、 <、 <=、 = =、 !=、 contains、 not contains、memberof、not memberof、matches、not matches;在這十二種類型的比較操做符當中,前六個是比較常見也是用的比較多的比較操做符
contains 示例代碼:
rule "rule1"
when
$order:Order();
$customer:Customer(age >20, orders contains $order);
then
System.out.println($customer.getName());
endoop
not contains 示例代碼:
rule "rule1"
when
$order:Order(items not contains "手機");
then
System.out.println($order.getName());
end
memberOf(memberOf 是用來判斷某個 Fact 對象的某個字段是否在一個集合(Collection/Array)當中) 示例代碼:
global String[] orderNames; //定義全局變量
rule "rule1"
when
$order:Order(name memberOf orderNames);
then
System.out.println($order.getName());
end
not memberOf (該操做符與 memberOf 做用洽洽相反) 示例代碼:
rule "rule1"
when
$orderList:String[]();
$order:Order(name not memberOf $orderList);
then
System.out.println($order.getName());
end
matches 是用來對某個 Fact 的字段與標準的 Java 正則表達式進行類似匹配,被比較的字符串能夠是一個標準的 Java 正則表達式,但有一點須要注意,那就是正則表達式字符串當中不用考慮「\」的轉義問題。
示例代碼:
rule "rule1"
when
$customer:Customer(name matches "李.*");
then
System.out.println($customer.getName());
end學習
not matches (該操做符與 matches 做用洽洽相反)操作系統
結果部分線程
咱們知道,在規則當中 LHS 就是用來放置條件的,因此在 RHS 當中雖然能夠直接編寫
Java 代碼,但不建議在代碼當中有條件判斷,若是須要條件判斷,那麼請從新考慮將其放在
LHS 當中,不然就違背了使用規則的初衷orm
在 Drools 當中,在 RHS 裏面,提供了一些對當前 Working Memory 實現快速操做的宏
宏函數或對象, 好比 insert/insertLogical、 update 和 retract 就能夠實現對當前 Working Memory
中的 Fact 對象進行新增、刪除或者是修改對象
1.insert
函數insert的做用與咱們在Java類當中調用StatefulKnowledgeSession對象的insert方法的做用相同,都是用來將一個 Fact 對象插入到當前的 Working Memory 當中
需注意:一旦調用 insert 宏函數,那麼 Drools 會從新與全部的規則再從新匹配一次, 對於沒有設置no-loop 屬性爲 true 的規則,若是條件知足,無論其以前是否執行過都會再執行一次,這個特性不只存在於 insert 宏函數上,後面介紹的 update、retract 宏函數一樣具備該特性,因此在某些狀況下因考慮不周調用 insert、update 或 retract 容易發生死循環
示例代碼以下:
rule "rule1"
salience 1 //該屬性的做用是經過一個數字來確認規則執行的優先級, 數字越大, 執行越靠前
when
eval(true); //默認成立
then
Customer cus=new Customer();
cus.setName("張三");
insert(cus);
end
rule "rule2"
salience 2
when
$customer:Customer(name =="張三");
then
System.out.println("rule2----"+$customer.getName());
end
2.insertLogical
insertLogical 做用與 insert 相似,它的做用也是將一個 Fact 對象插入到當前的 Working Memroy 當中
3.update
update函數意義與其名稱同樣, 用來實現對當前Working Memory當中的 Fact進行更新,update 宏函數的做用與 StatefulSession 對象的 update 方法的做用基本相同,都是用來告訴當
前的 Working Memory 該 Fact 對象已經發生了變化。它的用法有兩種形式,一種是直接更新一個 Fact 對象,另外一種爲經過指定 FactHandle 來更新與指定 FactHandle 對應的 Fact 對象
第一種 直接更新一個 Fact 對象:
rule "rule1"
salience 2
when
eval(true);
then
Customer cus=new Customer();
cus.setName("張三");
cus.setAge(1);
insert(cus);
end
rule "rule2"
salience 1
when
$customer:Customer(name=="張三",age<10);
then
$customer.setAge($customer.getAge()+1);
update($customer);
System.out.println("----------"+$customer.getName());
end
第二種 能夠支持建立一個新的 Fact 對象, 從而把 FactHandle對象指定的 Fact 對象替換掉,從而實現對象的全新更新:
rule "rule1"
salience 2
when
eval(true);
then
Customer cus=new Customer();
cus.setName("張三");
cus.setAge(1);
insert(cus);
end
rule "rule2"
salience 1
when
$customer:Customer(name=="張三",age<10);
then
Customer customer=new Customer();
customer.setName("張三");
customer.setAge($customer.getAge()+1);
update(drools.getWorkingMemory().getFactHandleByIdentity($customer),customer);
System.out.println("----------"+$customer.getName());
end
4.retract
retract用來將 Working Memory 當中某個 Fact 對象從 Working Memory 當中刪除 示例代碼:
rule "rule1"
salience 2
when
eval(true);
then
Customer cus=new Customer();
cus.setName("張三");
cus.setAge(1);
insert(cus);
end
rule "rule2"
salience 1
when
$customer:Customer(name=="張三");
then
retract($customer);
end
5.modify
modify是一個表達式塊,它能夠快速實現對 Fact 對象多個屬性進行修改,修改完成後會自動更新到當前的 Working Memory 當中
rule "rule1"
salience 2
when
$customer:Customer(name=="張三",age==20);
then
System.out.println("modify before customer
id:"+$customer.getId()+";age:"+$customer.getAge());
modify($customer){
setId("super man"),
setAge(30),
setName("黃五")
}
end
rule "rule2"
salience 1
when
$customer:Customer(name=="黃五");
then
System.out.println("modify after customer
id:"+$customer.getId()+";age:"+$customer.getAge());
end
屬性部分
1.salience
做用是用來設置規則執行的優先級,salience 屬性的值是一個數字,數字越大執行優先級越高,同時它的值能夠是一個負數。默認狀況下,規則的 salience 默認值爲 0,因此若是咱們不手動設置規則的 salience 屬性,那麼它的執行順序是隨機的。
示例代碼:
rule "rule1"
salience 1
when
eval(true)
then
System.out.println("rule1");
end
rule "rule2"
salience 2
when
eval(true)
then
System.out.println("rule2");
end
雖然 rule1 位於前面,但由於它的 salience 爲 1,而 rule2的 salience 屬性爲 2,因此 rule2 會先執行,而後 rule1 纔會執行。
2.no-loop
做用是用來控制已經執行過的規則在條件再次知足時是否再次執行。no-loop 屬性的值是一個布爾型,默認狀況下規則的 no-loop屬性的值爲 false,若是 no-loop 屬性值爲 true,那麼就表示該規則只會被引擎檢查一次,
若是知足條件就執行規則的 RHS 部分,若是引擎內部由於對 Fact 更新引發引擎再次啓動檢查規則,那麼它會忽略掉全部的 no-loop 屬性設置爲 true 的規則。
示例代碼:
rule "rule1"
salience 1
no-loop true
when
$customer:Customer(name=="張三")
then
update($customer);
System.out.println("customer name:"+$customer.getName());
End
3.date-effective 做用是用來控制規則只有在到達後纔會觸發,在規則運行時,引擎會自動拿當前操做系統的時候與 date-effective 設置的時間值進行比對, 只有當系統時間>=date-effective 設置的時間值時, 規則纔會觸發執行,不然執行將不執行。在沒有設置該屬性的狀況下,規則隨時能夠觸發,沒有這種限制。date-effective 的值爲一個日期型的字符串,默認狀況下,date-effective 可接受的日期格式爲「dd-MMM-yyyy」 示例代碼: rule "rule1" date-effective "2009-09-25" //當前日期不小於2009-09-25時能夠執行 when eval(true); then System.out.println("rule1 is execution!"); end 在實際使用的過程中,若是您不想用這種時間的格式,那麼能夠在調用的 Java 代碼中經過使用 System.setProperty(String key,String value)方法來修改默認的時間格式 在java文件中添加此條命令: System.setProperty("drools.dateformat","yyyy-MM-dd"); 4.date-expires 做用是與 date-effective 屬性偏偏相反, date-expires 的做用是用來設置規則的有效期,引擎在執行規則的時候,會檢查規則有沒有 date-expires 屬性,若是有的話,那麼會將這個屬性的值與當前系統時間進行比對,若是大於系統時間,那麼規則就執行,不然就不執行。 示例代碼: rule "rule1" date-effective "2009-09-25" //當前日期不小於2009-09-25時能夠執行(含2009-09-25) 注意修改時間格式 date-expires "2009-09-30" //當前日期大於2009-09-30時能夠執行(不含2009-09-30) 注意修改時間格式 when eval(true); then System.out.println("rule1 is execution!"); end 5.enabled 做用是用來定義一個規則是否可用的。該屬性的值是一個布爾值,默認該屬性的值爲 true,表示規則是可用的。設置其 enabled 屬性值爲 false,那麼引擎就不會執行該規則 6.dialect 做用是用來定義規則當中要使用的語言類型,目前支持兩種類型的語言:mvel 和 java,默認狀況下,若是沒有手工設置規則的 dialect,那麼使用的 java 語言 7.duration 做用是將在該屬性指定的值以後在另一個線程裏觸發。該屬性對應的值爲一個長整型,單位是毫秒 示例代碼: rule "rule1" duration 3000 when eval(true) then System.out.println("rule thread id:"+Thread.currentThread().getId()); end 8.lock-on-active 做用是 no-loop 的加強版屬性,它主要做用在使用 ruleflow-group 屬性或 agenda-group 屬性的時候。lock-on-active 屬性默認值爲 false。 9.activation-group 做用是將若干個規則劃分紅一個組,用一個字符串來給這個組命名,這樣在執行的時候,具備相同 activation-group 屬性的規則中只要有一個會被執行,其它的規則都將再也不執行。 也就是說,在一組具備相同 activation-group 屬性的規則當中,只有一個規則會被執行,其它規則都將不會被執行。固然對於具備相同 activation-group 屬性的規則當中究竟哪個會先執行,則能夠用相似 salience 之類屬性來實現。 示例代碼: rule "rule1" activation-group "test" when eval(true) then System.out.println("rule1 execute"); end rule "rule 2" activation-group "test" when eval(true) then System.out.println("rule2 execute"); end 10.agenda-group 做用是agenda-group 屬性的值也是一個字符串,經過這個字符串,能夠將規則分爲若干個Agenda Group,默認狀況下,引擎在調用這些設置了 agenda-group 屬性的規則的時候須要顯 示的指定某個 Agenda Group 獲得 Focus (焦點) , 這樣位於該 Agenda Group 當中的規則纔會觸發執行,不然將不執行。 示例代碼: rule "rule1" agenda-group "001" when eval(true) then System.out.println("rule1 execute"); end rule "rule 2" agenda-group "002" when eval(true) then System.out.println("rule2 execute"); end java調用: StatefulKnowledgeSession statefulSession = knowledgeBase.newStatefulKnowledgeSession(); statefulSession.getAgenda().getAgendaGroup("002").setFocus(); //得到執行焦點 statefulSession.fireAllRules(); statefulSession.dispose(); //瞭解便可 不經常使用 11.auto-focus 做用是用來在已設置了 agenda-group 的規則上設置該規則是否能夠自動獨取 Focus,若是該屬性設置爲 true,那麼在引擎執行時,就不須要顯示的爲某個 Agenda Group 設置 Focus,不然須要。 12.ruleflow-group 做用是用來將規則劃分爲一個個的組,而後在規則流當中經過使用 ruleflow-group 屬性的值,從而使用對應的規則。