drools中then部分的寫法(推薦)
1、背景
此處介紹一下drools
中then
部分的寫法,以及一些內(nèi)置的方法,比如insert/delete/modify
等等。同時(shí)也介紹一下rule
的繼承,和在when
中實(shí)現(xiàn)if else if
等操作。
2、支持的方法
drools提供了一些內(nèi)置的方法,這些方法會(huì)修改drools的工作內(nèi)存
中Fact
對(duì)象的值。從而會(huì)導(dǎo)致重新進(jìn)行模式匹配。
2.1 insert 插入對(duì)象到工作內(nèi)存中
insert
是向工作內(nèi)存中插入對(duì)象,同時(shí)會(huì)導(dǎo)致重新進(jìn)行規(guī)則的模式匹配。同時(shí)當(dāng)規(guī)則不滿足時(shí),不會(huì)自動(dòng)刪除。
2.1.1 需求
當(dāng)發(fā)生火災(zāi)Fire
時(shí),向工作內(nèi)存中插入一個(gè)Alarm
對(duì)象,告警發(fā)生后,刪除工作內(nèi)存中的Fire
對(duì)象,然后檢測Alarm
對(duì)象是否還存在。
2.1.2 drl文件編寫
package rules import com.huan.drools.insertmethod.Fire import com.huan.drools.insertmethod.Alarm rule "insert_發(fā)生火災(zāi)時(shí),往工作內(nèi)存中插入告警對(duì)象" when $fire: Fire() then System.out.println("1、發(fā)生火災(zāi)時(shí),往工作內(nèi)存中插入告警對(duì)象"); insert(new Alarm($fire)); end rule "insert_當(dāng)規(guī)則內(nèi)存中存在告警對(duì)象,進(jìn)行告警,然后刪除火災(zāi)對(duì)象" when $fire: Fire() $alarm: Alarm( fire == $fire ) then System.out.println("2、進(jìn)行告警,然后刪除對(duì)應(yīng)的火災(zāi)對(duì)象"); end rule "insert_檢測告警對(duì)象是否還是存在-01" when Alarm() then System.out.println("3、insert 插入的告警對(duì)象還存在"); // 刪除工作內(nèi)存中的Fire對(duì)象 delete($fire); end rule "insert_檢測告警對(duì)象不存在" when not Alarm() then System.out.println("3、insert 插入的告警對(duì)象不存在"); end
此處使用的是 insert
進(jìn)行插入
2.1.3 部分java代碼編寫
// 將火災(zāi)對(duì)象插入到工作內(nèi)存中 kieSession.insert(new Fire()); // 只觸發(fā)規(guī)則名稱以 insert_ 開頭的規(guī)則 kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("insert_"));
2.1.4 運(yùn)行結(jié)果
1、發(fā)生火災(zāi)時(shí),往工作內(nèi)存中插入告警對(duì)象
2、進(jìn)行告警,然后刪除對(duì)應(yīng)的火災(zāi)對(duì)象
3、insert 插入的告警對(duì)象還存在
2.1.5 結(jié)論
- insert可以向工作內(nèi)存中插入Fact對(duì)象。
- insert方法調(diào)用后,會(huì)導(dǎo)致模式的重新匹配,導(dǎo)致之前不會(huì)執(zhí)行的規(guī)則,重新執(zhí)行。
- insert方法插入到工作內(nèi)存的對(duì)象,在規(guī)則不成立時(shí),不會(huì)自動(dòng)刪除,需要手動(dòng)刪除,注意和insertLogical的區(qū)別
2.2 insertLogical 插入對(duì)象到工作內(nèi)存中
insert
是向工作內(nèi)存中插入對(duì)象,同時(shí)會(huì)導(dǎo)致重新進(jìn)行規(guī)則的模式匹配。同時(shí)當(dāng)規(guī)則不滿足時(shí),會(huì)自動(dòng)刪除。
2.2.1 需求
當(dāng)發(fā)生火災(zāi)Fire
時(shí),向工作內(nèi)存中插入一個(gè)Alarm
對(duì)象,告警發(fā)生后,刪除工作內(nèi)存中的Fire
對(duì)象,然后檢測Alarm
對(duì)象是否還存在。
2.2.2 drl文件編寫
package rules import com.huan.drools.Fire import com.huan.drools.Alarm rule "insertLogical_發(fā)生火災(zāi)時(shí),往工作內(nèi)存中插入告警對(duì)象" when $fire: Fire() then System.out.println("1、發(fā)生火災(zāi)時(shí),往工作內(nèi)存中插入告警對(duì)象"); insertLogical(new Alarm($fire)); end rule "insertLogical_當(dāng)規(guī)則內(nèi)存中存在告警對(duì)象,進(jìn)行告警,然后刪除火災(zāi)對(duì)象" when $fire: Fire() $alarm: Alarm( fire == $fire ) then System.out.println("2、進(jìn)行告警,然后刪除對(duì)應(yīng)的火災(zāi)對(duì)象"); delete($fire); end rule "insertLogical_檢測告警對(duì)象是否還是存在-01" when Alarm() then System.out.println("3、insertLogical 插入的告警對(duì)象還存在"); end rule "insertLogical_檢測告警對(duì)象不存在" when not Alarm() then System.out.println("3、insertLogical 插入的告警對(duì)象不存在"); end
此處使用的是insertLogical
插入
2.2.3 部分java代碼編寫
kieSession.insert(new Fire()); kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("insertLogical_"));
2.2.4 運(yùn)行結(jié)果
1、發(fā)生火災(zāi)時(shí),往工作內(nèi)存中插入告警對(duì)象
2、進(jìn)行告警,然后刪除對(duì)應(yīng)的火災(zāi)對(duì)象
3、insertLogical 插入的告警對(duì)象不存在
2.2.5 結(jié)論
- insertLogical可以向工作內(nèi)存中插入Fact對(duì)象。
- insertLogical方法調(diào)用后,會(huì)導(dǎo)致模式的重新匹配,導(dǎo)致之前不會(huì)執(zhí)行的規(guī)則,重新執(zhí)行。
- insertLogical方法插入到工作內(nèi)存的對(duì)象,在規(guī)則不成立時(shí),會(huì)自動(dòng)刪除注意和insert的區(qū)別
2.3、update 更新工作內(nèi)存中的對(duì)象
update:
使用它來指定要更新的字段和整個(gè)相關(guān)Fact,并將更改通知 Drools 引擎。 Fact發(fā)生更改后,您必須在更改可能受更新值影響的另一個(gè)事實(shí)之前調(diào)用 update。 為避免此添加步驟,請(qǐng)改用 modify 方法。
2.3.1 需求
規(guī)則一: 當(dāng)工作內(nèi)存中存在火災(zāi)對(duì)象Fire
,并且名字name為空時(shí)觸發(fā)規(guī)則,同時(shí)在設(shè)置火災(zāi)的名字為大火災(zāi)
。
規(guī)則二: 當(dāng)火災(zāi)存在名字時(shí),輸出火災(zāi)名字
2.3.2 drl 文件編寫
package rules import com.huan.drools.Fire import com.huan.drools.Alarm rule "update_當(dāng)存在火災(zāi)對(duì)象時(shí),設(shè)置一個(gè)火災(zāi)的名字" when $fire: Fire(name == null) then System.out.println("1、設(shè)置火災(zāi)名字"); $fire.setName("大火災(zāi)"); update($fire) end rule "update_當(dāng)火災(zāi)對(duì)象存在名字時(shí)觸發(fā)" when $fire: Fire(name != null) then System.out.println("2、火災(zāi)對(duì)象的名字為: " + $fire.getName()); end
2.3.3 部分java文件編寫
kieSession.insert(new Fire()); kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("update_"));
2.3.4 運(yùn)行結(jié)果
1、設(shè)置火災(zāi)名字
2、火災(zāi)對(duì)象的名字為: 大火災(zāi)
2.3.4 結(jié)論
update
會(huì)導(dǎo)致模式的重新匹配。update
會(huì)修改工作對(duì)象內(nèi)存中的值。
2.4、modify 更新工作內(nèi)存中的對(duì)象
modify:
使用它來指定要為Fact對(duì)象修改的字段并將更改通知 Drools 引擎。 此方法提供了一種結(jié)構(gòu)化的事實(shí)更新方法。 它將更新操作與 setter 調(diào)用相結(jié)合以更改對(duì)象字段。
2.4.1 需求
規(guī)則一: 當(dāng)工作內(nèi)存中存在火災(zāi)對(duì)象Fire
,并且名字name為空時(shí)觸發(fā)規(guī)則,同時(shí)在設(shè)置火災(zāi)的名字為大火災(zāi)
。
規(guī)則二: 當(dāng)火災(zāi)存在名字時(shí),輸出火災(zāi)名字
2.4.2 drl 文件編寫
package rules import com.huan.drools.Fire import com.huan.drools.Alarm rule "modify_當(dāng)存在火災(zāi)對(duì)象時(shí),設(shè)置一個(gè)火災(zāi)的名字" when $fire: Fire(name == null) then System.out.println("1、設(shè)置火災(zāi)名字"); modify($fire){ setName("大火災(zāi)") } end rule "modify_當(dāng)火災(zāi)對(duì)象存在名字時(shí)觸發(fā)" when $fire: Fire(name != null) then System.out.println("2、火災(zāi)對(duì)象的名字為: " + $fire.getName()); end
2.4.3 部分java文件編寫
kieSession.insert(new Fire()); kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("modify_"));
2.4.4 運(yùn)行結(jié)果
- 1、設(shè)置火災(zāi)名字
- 2、火災(zāi)對(duì)象的名字為: 大火災(zāi)
2.4.5 結(jié)論
modify
會(huì)導(dǎo)致模式的重新匹配。modify
會(huì)修改工作對(duì)象內(nèi)存中的值。一般情況下使用modify
,不要使用update
。
2.5 delete 刪除工作內(nèi)存中的對(duì)象
用法:delete(<object>)
retract
也是和delete
一樣的效果,但是推薦使用delete
。
3、drools變量的簡單使用
package rules rule "drools_變量的使用" wh eval(true) then System.out.println("Match激活的當(dāng)前觸發(fā)規(guī)則: " + drools.getMatch()); System.out.println("當(dāng)前觸發(fā)規(guī)則的名字: " + drools.getRule().getName()); // System.out.println("終止規(guī)則執(zhí)行fireUntilHalt(): " + drools.getKieRuntime().halt()); // System.out.println("激活A(yù)gendaGroup組: " + drools.getKieRuntime().getAgenda().getAgendaGroup( "CleanUp" ).setFocus()); System.out.println("獲取所有全局變量: " + drools.getKieRuntime().getGlobals()); // System.out.println("設(shè)置全局變量:" + drools.getKieRuntime().setGlobal("username","huan"); ); // System.out.println("獲取查詢結(jié)果:" + drools.getKieRuntime().getQueryResults()); end
4、規(guī)則的繼承
4.1 需求
規(guī)則一: 如果用戶(customer
)的年齡(age
)大于60歲,則打0.9
折。
規(guī)則二: 在規(guī)則一的基礎(chǔ)上,如果用戶有車(car
),則可以免費(fèi)停車(freeParking
)。
4.2 drl文件編寫
package rules import com.huan.drools.Customer import com.huan.drools.Car rule "rule_extends_規(guī)則一" when $c: Customer(age > 60) then modify($c){ setDiscount(0.9) } System.out.println("觸發(fā)規(guī)則一:用戶年齡>60歲,打0.9折"); end // 規(guī)則二繼承規(guī)則一的條件 rule "rule_extends_規(guī)則二" extends "rule_extends_規(guī)則一" when $car: Car() then modify($car){ setFreeParking(true) } System.out.println("觸發(fā)規(guī)則二:用戶有車,免費(fèi)停車"); end
此處rule_extends_規(guī)則二
繼承了rule_extends_規(guī)則一
,所以規(guī)則一的條件也繼承了。
4.3 部分java代碼
Car car = new Car(); Customer customer = new Customer(); customer.setAge(65); kieSession.insert(customer); kieSession.insert(car); kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("rule_extends_"));
客戶有車,并且年齡是65歲,滿足上方的規(guī)則一和規(guī)則二
4.4 運(yùn)行結(jié)果
觸發(fā)規(guī)則一:用戶年齡>60歲,打0.9折
觸發(fā)規(guī)則二:用戶有車,免費(fèi)停車
4.5 結(jié)論
可以看到在rule
上使用extends
關(guān)鍵字,可以實(shí)現(xiàn)規(guī)則的繼承。
5、使用do[...]語法重寫上方繼承的例子
5.1 需求
只要用戶大于60歲,直接打0.9折,如果還有車,則可以免費(fèi)停車。
5.2 drl文件編寫
package rules import com.huan.drools.Customer import com.huan.drools.Car rule "命名結(jié)果_rule" when $c: Customer(age > 60) do[giveDiscount] // 當(dāng)上方的條件成立時(shí)執(zhí)行 then [giveDiscount] $car: Car() // 此條件成立時(shí),執(zhí)行默認(rèn)的 then then modify($car){ setFreeParking(true) }; System.out.println("用戶有車,免費(fèi)停車"); then [giveDiscount] modify($c){ setDiscount(0.9) }; System.out.println("用戶年齡>60歲,打0.9折"); end
解釋:
見上方的規(guī)則文件里的注視
5.3 部分java代碼編寫
Car car = new Car(); Customer customer = new Customer(); customer.setAge(65); kieSession.insert(customer); kieSession.insert(car); kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("命名結(jié)果_"));
5.4 運(yùn)行結(jié)果
用戶年齡>60歲,打0.9折
用戶有車,免費(fèi)停車
也實(shí)現(xiàn)了需求
5.5 結(jié)論
通過when
中使用 do[名字]
然后 then
then 名字
也可以實(shí)現(xiàn)。
6、實(shí)現(xiàn) if else if 的效果
6.1 需求
完成類似 if else if else
效果。見下方的各種執(zhí)行結(jié)果。
6.2 規(guī)則文件
rule "if else-if" when $customer: Customer(age > 60) // 規(guī)則內(nèi)存中存在Customer對(duì)象,并且age>60 if($customer.getLevel() == 1) do[level1] // 用戶的級(jí)別是1,執(zhí)行then[level1],然后繼續(xù)執(zhí)行下方的條件 else if ($customer.getLevel() == 2) break[level2] // 用戶的級(jí)別是2,執(zhí)行then[level2],不在執(zhí)行下方的條件 else do[levelOther] // 其他的level級(jí)別,執(zhí)行then[levelOther],然后在執(zhí)行下方的條件 Car() then System.out.println("我執(zhí)行了"); then[level1] System.out.println("level1"); then[level2] System.out.println("level2"); then[levelOther] System.out.println("levelOther"); end
6.3 執(zhí)行結(jié)果圖
6.4 各種執(zhí)行結(jié)果-也就是上圖的解釋
1、Customer
的age
小于60
。輸出:
沒有輸出。
2、Customer
的age
大于60
并且level=1
,沒有Car
。輸出:
level1
3、Customer
的age
大于60
并且level=1
,有Car
。輸出:
level1 我執(zhí)行了
4、Customer
的age
大于60
并且level=2
,沒有Car
。輸出:
level2
5、Customer
的age
大于60
并且level=2
,有Car
。輸出:
level2
6、Customer
的age
大于60
并且level=3
,沒有Car
。輸出:
levelOther
7、Customer
的age
大于60
并且level=3
,有Car
。輸出:
levelOther 我執(zhí)行了
6.5 do和 break 有什么區(qū)別
do
:執(zhí)行完之后,還會(huì)繼續(xù)判斷后面的執(zhí)行條件。 (即還會(huì)執(zhí)行后面的Car判斷,根據(jù)是否有Car獲取不同的結(jié)果
)break
:執(zhí)行完之后,不會(huì)在判斷后面的執(zhí)行條件。(即忽略了后面的Car判斷,rule執(zhí)行完了
)
7.完整代碼
https://gitee.com/huan1993/spring-cloud-parent/tree/master/drools/drools-drl-then
8.參考文檔
https://docs.drools.org/7.69.0.Final/drools-docs/html_single/index.html#drl-rules-THEN-con_drl-rules
到此這篇關(guān)于drools中then部分的寫法的文章就介紹到這了,更多相關(guān)drools中then寫法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
spring cloud實(shí)現(xiàn)前端跨域問題的解決方案
這篇文章主要介紹了 spring cloud實(shí)現(xiàn)前端跨域問題的解決方案,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-01-01SpringBoot 如何根據(jù)不同profile選擇不同配置
這篇文章主要介紹了SpringBoot 如何根據(jù)不同profile選擇不同配置的操作方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08Java將本地項(xiàng)目部署到Linux服務(wù)器的實(shí)踐
本文主要介紹了Java將本地項(xiàng)目部署到Linux服務(wù)器的實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧<BR>2022-06-06mybatis調(diào)用mysql存儲(chǔ)過程并獲取返回值方式
這篇文章主要介紹了mybatis調(diào)用mysql存儲(chǔ)過程并獲取返回值方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08關(guān)于@RequestBody和@RequestParam注解的使用詳解
這篇文章主要介紹了關(guān)于@RequestBody和@RequestParam注解的使用詳解,本文十分具有參考意義,希望可以幫助到你,如果有錯(cuò)誤的地方還望不吝賜教2023-03-03