Drools學習筆記

Drools是一款基于Java的開源規(guī)則引擎

實現(xiàn)了將業(yè)務決策從應用程序中分離出來簿寂。

優(yōu)點:

1钦椭、簡化系統(tǒng)架構拧额,優(yōu)化應用

2、提高系統(tǒng)的可維護性和維護成本

3彪腔、方便系統(tǒng)的整合

4侥锦、減少編寫“硬代碼”業(yè)務規(guī)則的成本和風險

Drools的基本工作工程

我們需要傳遞進去數(shù)據(jù),用于規(guī)則的檢查德挣,調用外部接口恭垦,同時還可能獲取規(guī)則執(zhí)行完畢之后得到的結果

Fact對象:

指傳遞給drools腳本的對象,是一個普通的javabean格嗅,原來javaBean對象的引用番挺,可以對該對象進行讀寫操作,并調用該對象的方法

當一個java bean插入到working Memory(內存存儲)中屯掖,規(guī)則使用的是原有對象的引用玄柏,規(guī)則通過對fact對象的讀寫,

實現(xiàn)對應用數(shù)據(jù)的讀寫贴铜,對其中的屬性粪摘,需要提供get和set方法瀑晒,規(guī)則中可以動態(tài)的前往working memory中插入刪除新的fact對象

Drools的基礎語法:

包路徑,引用徘意,規(guī)則體 (其中包路徑和規(guī)則體是必須的)

Drl文件內容:

例子:

hello.drl文件如下:

package rules.testword

rule "test001"  when

    //這里如果為空苔悦,則表示eval(true)then

    System.out.println("hello word");

end


package:包路徑,該路徑是邏輯路徑(可以隨便寫椎咧,但是不能不寫玖详,最好和文件目錄同名,以(.)的方式隔開)勤讽,規(guī)則文件中永遠是第一行

rule:規(guī)則體竹宋,以rule開頭,以end結尾地技,每個文件可以包含多個rule,規(guī)則體分為3個部分:LHS秒拔,RHS莫矗,屬性 三大部分

LHS:(Left Hand Side),條件部分砂缩,在一個規(guī)則當中“when”和“then”中間的部分就是LHS部分作谚,在LHS當中,可以包含0~N個條件庵芭,如果

LHS為空的話妹懒,那么引擎會自動添加一個eval(true)的條件,由于該條件總是返回true双吆,所以LHS為空的規(guī)則總是返回true眨唬。

RHS:(Right Hand Side),在一個規(guī)則中“then”后面的部分就是RHS好乐,只有在LHS的所有條件都滿足的情況下匾竿,RHS部分才會執(zhí)行。

RHS部分是規(guī)則真正做事情的部分蔚万,滿足條件觸發(fā)動作的操作部分岭妖,在RHS可以使用LHS部分當中的定義的綁定變量名,設置的全局變量反璃、

或者是直接編寫的java代碼昵慌,可以使用import的類。

不建議有條件判斷淮蜈。

可以使用快速操作working Memory的宏函數(shù)和對象斋攀,比如insert/insertLogical,update/modify和retract就可以實現(xiàn)對當前Working Memory中的Fact對象

進行新增,修改礁芦,或者刪除蜻韭,可以使用drool宏對象悼尾,Drools還提供了kcontext的宏對象,該對象可以直接訪問當前Working Memory的KnowledgeRuntime肖方。

import:導入規(guī)則文件需要使用到的外部變量闺魏,可以導入類,也可以是這個類中的靜態(tài)方法

例如:

import com.dinpay.dpp.rcp.service.util.RuleLogUtil; 導入類

import com.dinpay.dpp.rcp.service.util.RuleLogUtil.getLog;//導入靜態(tài)方法

Drools的API調用

API可以分為三類:規(guī)則編譯俯画,規(guī)則收集析桥,規(guī)則執(zhí)行

1、Kmodule.xml的編譯

存放在src/main/resources/META-INF/文件夾下

<?xml version="1.0" encoding="UTF-8"?>

<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">

? ? <kbase name="rules" packages="rules.testword">

? ? ? ? <ksession name="session"/>

? ? </kbase>

</kmodule>? ? ? ?

1)艰垂、可包含多個kbase泡仗,任意但不能重名

2)、有個packages猜憎,就是src/main/resources下面的文件夾名稱娩怎,可定義多個包,用逗號隔開

3)胰柑、ksession都一個name截亦,任意字符串但不能重名,可以有多個

4)柬讨、在運行時崩瓤、KieContainer會根據(jù)*Model對象來創(chuàng)建KieModule,KieBase踩官,KieSession對象却桶,其中KieModule和KieBase只會創(chuàng)建一次,而KieSession則可能創(chuàng)建多次

2蔗牡、API說明颖系,引入drools依賴jar包,drools-core辩越,kie-api集晚,drools-compiler

KieSession;

用于與規(guī)則引擎進行交互的會話

分為兩類:

有狀態(tài)KieSession:KieSession會在多次與規(guī)則引擎進行交互中区匣,維護會話狀態(tài)偷拔,type屬性值是stateful,

最后需要清理KieSession維護的狀態(tài)亏钩,調用dispose()方法

無狀態(tài)StatelessKieSession:StatelessKieSession隔離了每次與規(guī)則引擎的交互莲绰,不會維護會話狀態(tài),無副作用姑丑,type屬性值是stateless

應用場景:數(shù)據(jù)校驗蛤签,運算,數(shù)據(jù)過濾栅哀,消息路由震肮,任何能被描述成函數(shù)或公式的規(guī)則

Drools內部功能詳細介紹

規(guī)則文件

一個標準的規(guī)則文件的結構代碼:

package package-name(包名称龙,必須的,只限制于邏輯上的管理戳晌,若自定義查詢或者函數(shù)屬于同一個包名鲫尊,不管物理位置如何,都可以調用)

imports (需要導入的類名)

globals (全局變量)

functions (函數(shù))

queries (查詢)

rules (規(guī)則沦偎,可以多個)

package在規(guī)則文件中是第一行疫向,其他的順序可以是無序的,package對于規(guī)則文件中規(guī)則的管理只限于邏輯上的管理

規(guī)則語言

rule “name”

attributes ---->屬性

when

LHS ---->條件

then

RHS---->結果

end

一個規(guī)則包含三部分:唯有attributes部分可選豪嚎,其他都是必填信息

定義當前規(guī)則執(zhí)行的一些屬性等搔驼,比如是否可被重復執(zhí)行,過期時間侈询,生效時間等

LHS:定義當前規(guī)則的條件舌涨,如 when Message();判斷當前workingMemory中是否存在Message對象

RHS:可以寫java代碼,即當前規(guī)則條件滿足執(zhí)行的操作扔字,可以直接調用Fact對象的方法來操作應用

LHS:如果LHS部分為空泼菌,自動添加一個eval(true)操作

LHS部分是由一個或多個條件組成,條件又稱為pattern(匹配模式)啦租,多個pattern之間可以使用 and 或 or來進行連接,同時還可以使用小括號來確定pattern的優(yōu)先級

【綁定變量名:】Object(【filed 約束】)

對于一個pattern來說"綁定變量名"是可選的荒揣,如果在當前規(guī)則的LHS部分的其他pattern要使用這個對象篷角,那么可以通過為該對象綁定設定一個

綁定變量名來實現(xiàn)對其的引用,對于綁定變量的命名系任,通常的做法是為其添加一個 "$"符號作為前綴恳蹲,可以和Fact對象區(qū)分開來

綁定變量可以用于對象上,可以用于對象屬性上俩滥,"field約束"是指當前對象里相關字段的條件限制

rule "rule1"? ? when

? ? ? ? $customer:Customer()

? ? then

? ? ? ? ...

end? ? ? ? ? ?

規(guī)則中LHS部分單個pattern(模式)的情形嘉蕾。

規(guī)則中"$customer"就是綁定到Customer對象的"綁定變量名",該規(guī)則的LHS部分表示霜旧,要求Fact對象必須是Customer類型错忱,該條件滿足,那么它的LHS會返回true

rule "rule1"? ? when

? ? ? ? ? $customer:Customer(age>20,gender=="male")

? ? ? ? ? Order(customer==$customer,price>1000)

? ? then

? ? ? ? ? ...

end

  第一個pattern有三個約束

1挂据、對象類型必須是Customer以清;

2、Customer的age要大于20

3崎逃、Customer的gender要是male

第二個pattern有三個約束

1掷倔、對象類型必須是Order

2、Order對應的Customer必須是前面那個Customer

3个绍、當前這個Order的price要大于1000

這兩個pattern沒有符號連接勒葱,在Drools當中沒有連接符號浪汪,默認是and,只有兩個pattern(模式)都滿足才會返回true凛虽,每行可以用";"結束

約束連接

對象內部的多個約束連接 "&&"(and),"||"(or)和","(and)來實現(xiàn)

如果記性常量的比較死遭,必須通過eval(條件)或者對象引用比較對象屬性,不能單獨引用

12個類型比較操作符 >|<,>=|<=,==|!=,contains|not contains,memberOf|not memberOf,matches|not matches

Drools屬性說明

salience優(yōu)先級

作用:設置規(guī)則執(zhí)行的優(yōu)先級涩维,值是一個數(shù)字殃姓,數(shù)字越大執(zhí)行的優(yōu)先級越高,它的值可以是一個負數(shù)瓦阐,默認值是0

如果我們不手動設置salience屬性值蜗侈,則執(zhí)行順序是隨機的

no-loop防止死循環(huán)

在一個規(guī)則中如果條件滿足就對Working Memory當中的某個Fact對象進行修改,比如使用update將其更新到當前的Working Memory當中睡蟋,這時候引擎會再次檢查所有的規(guī)則是否滿足條件踏幻,如果滿足會再執(zhí)行,可能會出現(xiàn)死循環(huán)

作用:用來控制已經(jīng)執(zhí)行過的規(guī)則條件再次滿足時是否再次執(zhí)行戳杀,默認是false该面,如果屬性值是true,表示該規(guī)則只會被規(guī)則引擎檢查一次信卡,如果滿足條件就執(zhí)行規(guī)則的RHS部分

注意:如果引擎內部因為對Fact更新引起引擎再次啟動檢查規(guī)則隔缀,那么它會忽略掉所有的no-loop屬性設置為true的規(guī)則

例如以下情況:計算設置了no-loop為true也會出現(xiàn)死循環(huán)

package rules.testwordimport com.drools.test.Person

? ? rule test001

? ? ? ? no-looptrue? ? ? ? when

      $p:Person(name=="張三");

     then

      $p.setAge(50);

      update($p);

      System.out.println("設置no-loop時的效果");

  end

rule test002

  no-looptrue  when

    $p:Person(age==50);

  then

    $p.setName("張三");

    update($p);

    System.out.println("設置no-loop時的效果");

end?

date-effective日期比較小于等于

date-expires日期比較大于

Dialect方言

Enabled是否可用

lock-on-active規(guī)則執(zhí)行一次

當在規(guī)則上使用ruleflow-group屬性或agenda-group屬性的時候,將lock-on-active屬性的值設置為true傍菇,可以避免因某些Fact對象被修改而使已經(jīng)執(zhí)行過

的規(guī)則再次被激活執(zhí)行猾瘸。可以看出該屬性與no-loop屬性有相似之處丢习,no-loop屬性是為了避免Fact修改或調用了insert牵触,retract,update之類導致

規(guī)則再次激活執(zhí)行咐低,這里lock-on-active屬性也是這個作用揽思,lock-on-active是no-loop的增強版。

作用:在使用ruleflow-group屬性或agenda-group屬性的時候见擦,默認是false钉汗,設置為true,該規(guī)則只會執(zhí)行一次

activation-group分組

agenda-greoup議程分組

規(guī)則的調用與執(zhí)行是通過StatelessSession和ksession來實現(xiàn)的鲤屡,一般的順序是創(chuàng)建一個StatelessSession或ksession儡湾,

    將各種經(jīng)過編譯的規(guī)則的package添加到session當中,接下來將規(guī)則當中可能用到的Global對象和Fact對象插入到Session當中执俩,

    最后調用fireAllRules方法來觸發(fā)徐钠,執(zhí)行規(guī)則,在沒有調用最后一步分fireAllRules方法之前役首,

    所有的規(guī)則及插入的Fact對象都存放在Agenda表的對象當中尝丐,這個Agenda表中的每個規(guī)則及其匹配相關的業(yè)務數(shù)據(jù)叫做Activation显拜,

    在調用fireAllRules方法后,這些Activation會依次執(zhí)行爹袁,這些位于Agenda表中的Activation的執(zhí)行順序在沒有設置相關用來

    控制順序的時(比如:salience屬性)远荠,它的執(zhí)行順序是隨機不確定的。

    agenda-group是用來在Agenda基礎上失息,對現(xiàn)有的規(guī)則進行再次分組譬淳,具體的分組方法可以采用為規(guī)則添加agenda-group屬性來實現(xiàn),

    agenda-group屬性的值也是一個字符串盹兢,通過這個字符串邻梆,可以將規(guī)則分為若干個agenda group,默認情況下绎秒,引擎在調用這些

    設置了agenda-group屬性的規(guī)則的時候需要指定某個agenda group得到Focus(焦點)浦妄,這樣位于該agenda group當中的規(guī)則才會觸發(fā)執(zhí)行,否則將不執(zhí)行

實際應用中agenda-group可以和auto-focus屬性一起使用

auto-focus焦點分組

ruleflow-group規(guī)則流

Drools drl注釋的使用

單行// 多行/**/

Drools函數(shù)的使用

insert插入

語法格式:insert(new Object());

insertLogical插入

update修改

語法格式:update(Object());

retract刪除功能

drools常用方法

方法名稱            用法格式        含義

getWorkingMemory()  drools.getWorkingMemory()  獲取當前WorkingMemory對象

halt()       ? ? ? drools.halt()          ?在當前規(guī)則執(zhí)行完成之后见芹,不再執(zhí)行其他未執(zhí)行的規(guī)則

getRule()     ?? ? ?——             獲取當前規(guī)則對象

insert(new Object)   ?——          ? ? ? ? ? ? 插入指定對象

update(new Object)  ?—— ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 更新指定對象

update(FactHandleObject) ——          ? ? ? ? ? 更新指定對象

retract(new Object)  ——             ? ? 刪除指定對象

Drools語法篇之Global全局變量

global不是用來做數(shù)據(jù)共享的剂娄,session會影響到global的用法

注意:

1、常量值是不能改變的

2玄呛、包裝類是不能改變的

3阅懦、類似javaBean,List這類的操作徘铝,是可以改變內容的耳胎,但內存地址是不會變的

Drools語法篇之查詢Query

Drools語法篇之類的聲明及元數(shù)據(jù)的用法

聲明新類型:使用關鍵字declare,緊接著字段列表庭砍,和關鍵字end。

例如:

declare Address

? ? number:int? ? streetName:String

? ? city:String

end

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末混埠,一起剝皮案震驚了整個濱河市怠缸,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌钳宪,老刑警劉巖揭北,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異吏颖,居然都是意外死亡搔体,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進店門半醉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來疚俱,“玉大人,你說我怎么就攤上這事缩多〈艮龋” “怎么了养晋?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長梁钾。 經(jīng)常有香客問我绳泉,道長,這世上最難降的妖魔是什么姆泻? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任零酪,我火速辦了婚禮,結果婚禮上拇勃,老公的妹妹穿的比我還像新娘四苇。我一直安慰自己,他們只是感情好潜秋,可當我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布蛔琅。 她就那樣靜靜地躺著,像睡著了一般峻呛。 火紅的嫁衣襯著肌膚如雪罗售。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天钩述,我揣著相機與錄音寨躁,去河邊找鬼。 笑死牙勘,一個胖子當著我的面吹牛职恳,可吹牛的內容都是我干的。 我是一名探鬼主播方面,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼放钦,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了恭金?” 一聲冷哼從身側響起操禀,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎横腿,沒想到半個月后颓屑,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡耿焊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年揪惦,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片罗侯。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡器腋,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情蒂培,我是刑警寧澤再愈,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站护戳,受9級特大地震影響翎冲,放射性物質發(fā)生泄漏。R本人自食惡果不足惜媳荒,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一抗悍、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧钳枕,春花似錦缴渊、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至昔瞧,卻和暖如春指蚁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背自晰。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工凝化, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人酬荞。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓搓劫,卻偏偏與公主長得像,于是被迫代替她去往敵國和親混巧。 傳聞我的和親對象是個殘疾皇子枪向,可洞房花燭夜當晚...
    茶點故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內容