drools规则引擎介绍
1.drools是什么
Drools是為Java量身定制的基于Charles? Forgy的RETE算法的規(guī)則引擎的實(shí)現(xiàn)。具有了OO接口的RETE,使得商業(yè)規(guī)則有了更自然的表達(dá)。
Rule是什么呢?
?
一條規(guī)則是對(duì)商業(yè)知識(shí)的編碼。一條規(guī)則有?attributes?,一個(gè)?Left Hand Side?(?LHS?)和一個(gè)?Right Hand Side?(?RHS?)。Drools?允許下列幾種?attributes?:?salience?,?agenda-group?,?no-loop?,?auto-focus?,?duration?,?activation-group??。
規(guī)則的?LHS?由一個(gè)或多個(gè)條件(?Conditions?)組成。當(dāng)所有的條件(?Conditions?)都滿足并為真時(shí),?RHS?將被執(zhí)行。?RHS?被稱為結(jié)果(?Consequence?)。?LHS?和?RHS?類似于
if(<LHS>){
<RHS>
}
下面介紹幾個(gè)術(shù)語:
對(duì)新的數(shù)據(jù)和被修改的數(shù)據(jù)進(jìn)行規(guī)則的匹配稱為模式匹配(?Pattern Matching?)。進(jìn)行匹配的引擎稱為推理機(jī)(?Inference Engine?)。被訪問的規(guī)則稱為?ProductionMemory?,被推理機(jī)進(jìn)行匹配的數(shù)據(jù)稱為?WorkingMemory?。?Agenda?管理被匹配規(guī)則的執(zhí)行。推理機(jī)所采用的模式匹配算法有下列幾種:?Linear?,?RETE?,?Treat?,?Leaps?。這里注意加紅的地方,對(duì)數(shù)據(jù)的修改也會(huì)觸發(fā)重新匹配,即對(duì) WorkingMemory中的數(shù)據(jù)進(jìn)行了修改。
然后規(guī)則引擎大概是這個(gè)樣子的:
這個(gè)圖也很好理解,就是推理機(jī)拿到數(shù)據(jù)和規(guī)則后,進(jìn)行匹配,然后把匹配的規(guī)則和數(shù)據(jù)傳遞給Agenda。
規(guī)則引擎實(shí)現(xiàn)了數(shù)據(jù)同邏輯的完全解耦。規(guī)則并不能被直接調(diào)用,因?yàn)樗鼈儾皇欠椒ɑ蚝瘮?shù),規(guī)則的激發(fā)是對(duì)?WorkingMemory?中數(shù)據(jù)變化的響應(yīng)。結(jié)果(?Consequence?,即?RHS?)作為?LHS events?完全匹配的?Listener?。
數(shù)據(jù)被?assert?進(jìn)?WorkingMemory?后,和?RuleBase?中的?rule?進(jìn)行匹配(確切的說應(yīng)該是?rule?的?LHS?),如果匹配成功這條?rule?連同和它匹配的數(shù)據(jù)(此時(shí)就叫做?Activation?)一起被放入?Agenda?,等待?Agenda?來負(fù)責(zé)安排激發(fā)?Activation?(其實(shí)就是執(zhí)行?rule?的?RHS?),上圖中的菱形部分就是在?Agenda?中來執(zhí)行的,?Agenda?就會(huì)根據(jù)沖突解決策略來安排?Activation?的執(zhí)行順序。
下面附上drools規(guī)則引擎的執(zhí)行過程
?
2.rete算法
參考鏈接:Rete Algorithm
rete在拉丁文里是net network的意思,這個(gè)算法由?Charles Forgy ?博士在他的博士論文里提到。
這個(gè)算法可以分為兩個(gè)部分,一個(gè)是如何編譯規(guī)則,一個(gè)是如何執(zhí)行。原話(The Rete algorithm can be broken into 2 parts: rule compilation and runtime execution.)
rule compilation 就是如何通過對(duì)所有規(guī)則進(jìn)行處理,生成一個(gè)有效的辨別網(wǎng)絡(luò)。而一個(gè)辨別網(wǎng)絡(luò),則對(duì)數(shù)據(jù)進(jìn)行過濾,使數(shù)據(jù)一步步往下傳送。數(shù)據(jù)剛進(jìn)入網(wǎng)絡(luò),有很多的匹配條件,這里可以理解為:邏輯表達(dá)式為true or false,然后在網(wǎng)絡(luò)里往下傳遞的時(shí)候,匹配的條件越來越少,最后到達(dá)一個(gè)終止節(jié)點(diǎn)。
在這個(gè)論文里Dr Charles描述了這么幾個(gè)節(jié)點(diǎn),Node:
2.rete算法
參考鏈接:Rete Algorithm
rete在拉丁文里是net network的意思,這個(gè)算法由?Charles Forgy ?博士在他的博士論文里提到。
這個(gè)算法可以分為兩個(gè)部分,一個(gè)是如何編譯規(guī)則,一個(gè)是如何執(zhí)行。原話(The Rete algorithm can be broken into 2 parts: rule compilation and runtime execution.)
rule compilation 就是如何通過對(duì)所有規(guī)則進(jìn)行處理,生成一個(gè)有效的辨別網(wǎng)絡(luò)。而一個(gè)辨別網(wǎng)絡(luò),則對(duì)數(shù)據(jù)進(jìn)行過濾,使數(shù)據(jù)一步步往下傳送。數(shù)據(jù)剛進(jìn)入網(wǎng)絡(luò),有很多的匹配條件,這里可以理解為:邏輯表達(dá)式為true or false,然后在網(wǎng)絡(luò)里往下傳遞的時(shí)候,匹配的條件越來越少,最后到達(dá)一個(gè)終止節(jié)點(diǎn)。
在這個(gè)論文里Dr Charles描述了這么幾個(gè)節(jié)點(diǎn),Node:
?
這里對(duì)其中的幾個(gè)節(jié)點(diǎn)做一下簡(jiǎn)單介紹,另外說一下如何運(yùn)作的。
-
- 首先,root node是所有的對(duì)象都可以進(jìn)入的節(jié)點(diǎn),也是辨別網(wǎng)絡(luò)的一個(gè)入口,這個(gè)可以理解為一個(gè)虛節(jié)點(diǎn),其實(shí)可能并不存在。
- 然后立馬進(jìn)入到ObjectTypeNode節(jié)點(diǎn),這是一個(gè)對(duì)象類型節(jié)點(diǎn)。很明顯,這里承載的是一個(gè)對(duì)象,可以理解為是java中的某個(gè)new Object(),在這個(gè)算法里,這個(gè)節(jié)點(diǎn)的作用就是為了保證不做一些無用功,什么無用功呢,就是不是對(duì)每個(gè)規(guī)則,進(jìn)入的對(duì)象都要去辨別一遍,而是確定的對(duì)象類型,去做跟他相關(guān)的辨別,其實(shí)就是match。那么怎么做到呢?這里用到了一個(gè)hashMap,每次進(jìn)入網(wǎng)絡(luò)的對(duì)象,都會(huì)在這個(gè)map中通過hash,找到一個(gè)對(duì)應(yīng)的辨別路徑去辨別,即match。附上英文原文:(
Drools extends Rete by optimizing the propagation from ObjectTypeNode to AlphaNode using hashing. Each time an AlphaNode is added to an ObjectTypeNode it adds the literal value as a key to the HashMap with the AlphaNode as the value. When a new instance enters the ObjectType node, rather than propagating to each AlphaNode, it can instead retrieve the correct AlphaNode from the HashMap,thereby avoiding unnecessary literal checks.)
一個(gè)圖來說明:
所有經(jīng)過ObjectTypeNode的對(duì)象都會(huì)走到下一個(gè)節(jié)點(diǎn),下一個(gè)節(jié)點(diǎn)可以是下面的幾種:AlphaNodes, LeftInputAdapterNodes and BetaNodes。后面兩個(gè)節(jié)點(diǎn)是AlphaNodes節(jié)點(diǎn)的一些變種,AlphaNodes節(jié)點(diǎn)是用來判斷一些條件的。可以理解為一些邏輯表達(dá)式的計(jì)算。
下面開始上圖:
- 這個(gè)圖就是傳遞進(jìn)一個(gè)Cheese對(duì)象,然后依次判斷是否滿足條件:1.判斷name是否是“cheddar”,2.如果判斷1通過了,繼續(xù)判斷strength是否是strong。這是最簡(jiǎn)單了一種情況了,這里附上對(duì)應(yīng)的規(guī)則描述,后面會(huì)繼續(xù)講解:
rule "cheessRule" when
$cheese:Cheese(name == "cheddar" && strength == "strong")
then
......
end
?
3.maven依賴
這里列了一些后面的一些例子需要用到的maven依賴
<!--kie api 構(gòu)建kie虛擬文件系統(tǒng),關(guān)聯(lián)decisiontable和drl文件,很關(guān)鍵 --> <dependency><groupId>org.kie</groupId><artifactId>kie-api</artifactId> </dependency> <!-- 規(guī)則引擎核心包,里面包含了RETE引擎和LEAPS 引擎--> <dependency><groupId>org.drools</groupId><artifactId>drools-core</artifactId> </dependency> <dependency><groupId>org.drools</groupId><artifactId>drools-compiler</artifactId> </dependency> <!-- 決策表依賴--> <dependency><groupId>org.drools</groupId><artifactId>drools-decisiontables</artifactId> </dependency> <dependency><groupId>org.drools</groupId><artifactId>drools-templates</artifactId> </dependency>4.規(guī)則文件:.drl or xls
我們一般用到的也就這兩種形式,一個(gè)是drl文件,是drools規(guī)則引擎提供的最原生的方式,語法很簡(jiǎn)單,具體語法見drools語法介紹
還有一個(gè)是決策表,決策表可以是xls也可以是csv,我們一般用xls比較多。而且好理解。xls就是一個(gè)excel文件。ps:在使用的過程中,遇到很多坑,其中一個(gè)最大的坑是mac系統(tǒng)的問題,這里后面會(huì)安利。
drl文件
首先來看下drl文件,這個(gè)在第2條講解node的時(shí)候已經(jīng)提到過了。
舉例:
- package 定義了規(guī)則文件的一個(gè)命名空間,和java中的package無關(guān)。
- import 這里可以有多個(gè),就是在規(guī)則文件里引用到的java類。
- rule 用來定義一個(gè)規(guī)則,這里名字不可重復(fù),后面跟一個(gè)when關(guān)鍵字,翻譯過來就是,規(guī)則 名ageUp12,當(dāng)滿足......
- when 和then之間是邏輯表達(dá)式,也就是辨別條件,其中$student:Student(age >2)這里其實(shí)包含了兩個(gè)意思,一個(gè)是滿足age>2的Student對(duì)象,一個(gè)是把這個(gè)對(duì)象賦值給$student變量,這樣后面就可以引用這個(gè)變量了。邏輯表達(dá)式寫在小括號(hào)里,如果是多個(gè)條件,可以用逗號(hào)分隔,如$sutdent :Student(age > 2,name=="max")
- then和end之間來定義action,即當(dāng)滿足age>2的時(shí)候,做什么操作,這里可以像在java方法里一樣,調(diào)用任何一個(gè)java類的方法,只要import了這個(gè)類且在前面定義了這個(gè)變量
第二個(gè)例子可以看到有個(gè)retract($student),這里是用到了drools內(nèi)部提供的一個(gè)函數(shù),具體見后續(xù)關(guān)于drools語法介紹的博客
決策表(decisiontable)
決策表就是一個(gè)excel文件,可以是xls(xlsx暫不支持)或者csv是個(gè)表格,看上去也很直觀,即便是不懂代碼的人看了也能看懂,不像drl文件那么多語法。關(guān)鍵的一點(diǎn)是:decisiontable也是最終轉(zhuǎn)成drl文件來讓drools規(guī)則引擎來解析執(zhí)行的。*.xls到*.drl的轉(zhuǎn)換這個(gè)在后面的wiki會(huì)說到。
直接上圖吧
這里可以暫時(shí)忽略那些背景色,只是為了好區(qū)分沒個(gè)模塊的作用
這里忽略文件開始的空行,從有數(shù)據(jù)的第一行開始解釋說明:
第一行,第一列:RuleSet 第二列com.sankuai.meituan.maxtse.drools.test。這里RuleSet可以省略的,累似drl文件中的package
第二行,第一列:Import 第二列具體的java類,這里和drl文件里的Improt相對(duì)應(yīng),多個(gè)引用類用逗號(hào)分隔
第三行,是個(gè)對(duì)這個(gè)決策表的說明
第四行,第一列:RuleTable FirstDecisionTable 這一行很關(guān)鍵 指明這是一個(gè)決策表,并且下面的幾行都是具體的規(guī)則,就好比上面幾行是一些準(zhǔn)備條件,下面才是真正干活的地方,這里來個(gè)說明
第五行,CONDITION行,這一行可以有兩種列名:CONDITION ACTION。CONDITION列就是drl里的辨別條件, ?ACTION則是具體的操作,即滿足前面幾列的CONDITION的條件后,會(huì)執(zhí)行什么操作,這里CONDITION一定在ACTION前面,ACTION可以有多個(gè)列, 單個(gè)ACTION里的多個(gè)操作用逗號(hào)分隔,末尾要加分號(hào)結(jié)尾這里很重要,不然會(huì)有解析錯(cuò)誤
第六行,緊挨著CONDITION的一行,可以在這里聲明下面要用的到對(duì)象,對(duì)應(yīng)drl文件里的$student:Student()
第七行,是辨別條件邏輯表達(dá)式,如:student.getAge()==$param則對(duì)應(yīng)drl里的age==12這里$param是對(duì)應(yīng)列每個(gè)單元格的值,然后這里需要特別說明下,針對(duì)于非字符串,如整數(shù),小數(shù)等,可以直接使用$param,但是如果單元格里是字符串,則需要加雙引號(hào)。(ps:mac里的雙引號(hào)是斜的,一定要保證是豎著"的)另外,如果有多個(gè)值,可以用逗號(hào)隔開,然后可以用$1,$2提取變量值,如第一個(gè)ACTION里的student.doAction1($1,"$2")
第八行仍然是注釋行,可以添加每一個(gè)CONDITON ACTION列的說明。
下面的每一行就是對(duì)應(yīng)的某些條件的取值了。
總結(jié)
以上是生活随笔為你收集整理的drools规则引擎介绍的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PHP中过滤数组中的元素
- 下一篇: wps日期加减算天数_日期相减之后的天数