Drools規(guī)則引擎 系列教程(一)SpringBoot整合 & 快速集成上手
Drools規(guī)則引擎 系列教程(三)Drools規(guī)則語法 & RHS動(dòng)作 & header詳解
Drools規(guī)則引擎 系列教程(四)Drools 主要API & 決策表
教程代碼已提交到ytooo-drools,歡迎star
文中代碼方法均基于上一篇教程
1. .drl文件結(jié)構(gòu)
- package 包充當(dāng)每組規(guī)則的唯一名稱空間。一個(gè)規(guī)則庫可以包含多個(gè)程序包。
通常,將包的所有規(guī)則與包聲明存儲(chǔ)在同一文件中,以便包是獨(dú)立的。但是,
也可以在規(guī)則中使用從其他的包中導(dǎo)入的對象 - imports 與Java中的import語句類似,用來標(biāo)識(shí)在規(guī)則中使用的任何對象的標(biāo)準(zhǔn)路徑和類型名稱
- factions 函數(shù)代碼塊如:
function String hello(String applicantName) {
return "Hello " + applicantName + "!";
}
- queries 在Drools引擎的工作內(nèi)存中搜索與DRL文件中的規(guī)則相關(guān)的事實(shí)
query "people under the age of 21"
$person : Person( age < 21 )
end
- global 為規(guī)則提供數(shù)據(jù)或服務(wù)
- rules 規(guī)則
1.1 import引入java方法 以及 function
?? import & function 在下一節(jié)中詳細(xì)描述 帶我飛過去
1.2 glable 全局變量
?? 全局變量在下一節(jié)中詳細(xì)描述 帶我飛過去
1.3 querys 查詢
?? querys查詢在下一節(jié)中詳細(xì)描述 帶我飛過去
1.4 declare 自定義fact對象
?? declare在下一節(jié)中詳細(xì)描述 帶我飛過去
2.rules 規(guī)則
2.1 drl屬性
| 屬性 | 描述 |
|---|---|
| salience | 定義規(guī)則優(yōu)先級(jí)的整數(shù),數(shù)值越大,優(yōu)先級(jí)越高 |
| enabled | 規(guī)則啟用開關(guān) |
| date-effective | 包含日期和時(shí)間定義的字符串。僅當(dāng)當(dāng)前日期和時(shí)間在date-effective屬性之后時(shí),才能激活該規(guī)則。 |
| date-expires | 如果當(dāng)前日期和時(shí)間在date-expires屬性之后,則無法激活該規(guī)則。 |
| no-loop | 選擇該選項(xiàng)后,如果規(guī)則的結(jié)果重新觸發(fā)了先前滿足的條件,則無法重新激活(循環(huán))規(guī)則。如果未選擇條件,則在這些情況下可以循環(huán)規(guī)則。 |
| agenda-group | 標(biāo)識(shí)要向其分配規(guī)則的議程組 |
| activation-group | 激活組,在激活組中,只能激活一個(gè)規(guī)則。觸發(fā)的第一個(gè)規(guī)則將取消激活組中所有規(guī)則的所有未決激活。 |
| duration | 定義了如果仍滿足規(guī)則條件,則可以激活規(guī)則的持續(xù)時(shí)間(以毫秒為單位)。 |
| timer | cron定時(shí)表達(dá)式 |
| calendar | 時(shí)鐘 |
| auto-focus | 僅適用于議程組中的規(guī)則。選擇該選項(xiàng)后,下次激活該規(guī)則時(shí),將自動(dòng)將焦點(diǎn)分配給分配了該規(guī)則的議程組。 |
| lock-on-active | no-loop屬性的更強(qiáng)版 |
| ruleflow-group | 標(biāo)識(shí)規(guī)則流組的字符串 |
| dialect | 用于標(biāo)識(shí)規(guī)則中的代碼表達(dá)式JAVA或MVEL將其用作語言 |
2.2 匹配模式
2.2.1 沒有約束的匹配模式
實(shí)事不需要滿足任何條件,若類型相同,則觸發(fā)該規(guī)則,如:
package com.ytooo.bean
import com.ytooo.bean.People
dialect "java"
rule "girl"
when
People()
then
System.out.println("girl規(guī)則執(zhí)行");
end
2.2.2 有條件約束的匹配模式
實(shí)事類型相同,且滿足條件,則觸發(fā)該規(guī)則,如:
package com.ytooo.bean
import com.ytooo.bean.People
dialect "java"
rule "girl"
when
People(sex == 0 && drlType == "people")
then
System.out.println("girl規(guī)則執(zhí)行");
end
2.2.3 匹配并綁定屬性以及實(shí)事
實(shí)事類型相同,且滿足條件,則觸發(fā)該規(guī)則,并綁定數(shù)據(jù),如:
package com.ytooo.bean
import com.ytooo.bean.People
dialect "java"
rule "girl"
when
$p:People(sex == 0,$sex : sex && drlType == "people")
then
System.out.println("girl規(guī)則執(zhí)行");
System.out.println($p);
System.out.println($sex);
end
2.3 條件
and,or 等結(jié)合規(guī)則條件的多個(gè)模式,沒有定義關(guān)鍵字連詞,默認(rèn)是and:
package com.ytooo.bean
import com.ytooo.bean.People
import com.ytooo.bean.Cat
dialect "java"
rule "girl"
when
People(sex == 0) and
Cat(sex == 0)
then
System.out.println("girl規(guī)則執(zhí)行");
end
2.4 約束
??標(biāo)準(zhǔn)Java運(yùn)算符優(yōu)先級(jí)適用于DRL中的約束運(yùn)算符,而drl運(yùn)算符除==和!=運(yùn)算符外均遵循標(biāo)準(zhǔn)Java語義。
??在drl中 Person( firstName != "John" )類似于 !java.util.Objects.equals(person.getFirstName(), "John")
| 約束 | 描述 |
|---|---|
| !. | 使用此運(yùn)算符可以以空安全的方式取消引用屬性。!.運(yùn)算符左側(cè)的值不能為null(解釋為!= null) |
| [] | 按List索引訪問值或Map按鍵訪問值 |
| <,<=,>,>= | 在具有自然順序的屬性上使用這些運(yùn)算符 |
| ==, != | 在約束中使用這些運(yùn)算符作為equals()和!equals()方法 |
| &&,|| | 組合關(guān)系條件 |
| matches,not matches | 使用這些運(yùn)算符可以指示字段與指定的Java正則表達(dá)式匹配或不匹配 |
| contains,not contains | 使用這些運(yùn)算符可以驗(yàn)證Array或字段是否包含或不包含指定值 |
| memberOf,not memberOf | 使用這些運(yùn)算符可以驗(yàn)證字段是否為定義為變量Array的成員 |
| soundslike | 使用英語發(fā)音來驗(yàn)證單詞是否具有與給定值幾乎相同的聲音(類似于該matches運(yùn)算符) |
| in,notin | 使用這些運(yùn)算符可以指定一個(gè)以上的可能值來匹配約束(復(fù)合值限制) |
2.4.1 約束demo
??來自官方文檔
- matches, not matches
Person( country matches "(USA)?\\S*UK" )
Person( country not matches "(USA)?\\S*UK" )
- contains, not contains
FamilyTree(countries contains "UK" )
Person( fullName not contains "Jr" )
FamilyTree(countries contains $var)
Person( fullName not contains $var )
- memberOf, not memberOf
FamilyTree( person memberOf $europeanDescendants )
FamilyTree( person not memberOf $europeanDescendants )
2.5 集合
2.5.1 from 取集合中的元素
新建bean Animal
package com.ytooo.bean;
import lombok.Data;
import java.util.List;
/**
* Created by Youdmeng on 2020/1/7 0007.
*/
@Data
public class Animal {
private Integer level;
private List<People> peoples;
}
新建 from.drl
package com.ytooo.frm
dialect "java"
import com.ytooo.bean.People
import com.ytooo.bean.Animal
rule "from"
when
$an : Animal()
$p : People(sex != 3 && drlType == "from") from $an.peoples
then
System.out.println($p);
end
新建測試方法
@Test
public void from() {
People p1 = new People(1,"達(dá)","from");
People p2 = new People(0,"秋","from");
People p3 = new People(3,"金","from");
Animal animal = new Animal();
animal.setPeoples(new ArrayList<>());
animal.getPeoples().add(p1);
animal.getPeoples().add(p2);
animal.getPeoples().add(p3);
session.insert(animal);//插入
session.fireAllRules();//執(zhí)行規(guī)則
}
執(zhí)行測試,在三組數(shù)據(jù)中,2個(gè)people滿足條件,執(zhí)行兩次
People(sex=0, name=秋, drlType=from)
People(sex=1, name=達(dá), drlType=from)
2.5.2 collect
??從指定來源或從Drools引擎的工作內(nèi)存中獲取集合,可以使用Java集合(例如List,LinkedList和HashSet)
新建 collect.drl
package com.ytooo.collt
dialect "java"
import com.ytooo.bean.People
import java.util.List
rule "collect"
when
$alarms : List( size >= 3 ) from collect(People(sex != 3 && drlType == "collect"))
then
System.out.println("collect執(zhí)行成功,匹配結(jié)果為:"+$alarms);
end
新建測試方法
@Test
public void collect() {
session.insert(new People(1, "達(dá)","collect"));
session.insert(new People(0, "秋","collect"));
session.insert(new People(0, "春","collect"));
session.insert(new People(1, "夏","collect"));
session.insert(new People(0, "冬","collect"));
session.insert(new People(3, "金","collect"));
session.fireAllRules();//執(zhí)行規(guī)則
}
執(zhí)行測試,正確打印出匹配的實(shí)事,其中 sex=3的“金” 沒有匹配到結(jié)果中
collect執(zhí)行成功,匹配結(jié)果為:
[People(sex=0, name=冬, drlType=collect),
People(sex=1, name=夏, drlType=collect),
People(sex=0, name=春, drlType=collect),
People(sex=0, name=秋, drlType=collect),
People(sex=1, name=達(dá), drlType=collect)]
??當(dāng)改變參數(shù),入?yún)⒅涣粝聝蓚€(gè) sex != 3 的數(shù)據(jù),則沒有任何打印結(jié)果
2.5.3 accumulate 迭代器
??用于遍歷數(shù)據(jù)集對數(shù)據(jù)項(xiàng)執(zhí)行自定義或預(yù)設(shè)動(dòng)作并返回結(jié)果。
2.5.3.1 accumulate 函數(shù)
- average
- min
- max
- count
- sum
- collectList 獲取列表
- collectSet 獲取集合
average樣例 新建 accumulate.drl
package com.ytooo.collt
dialect "java"
import com.ytooo.bean.Sensor
import java.util.List
rule "accumulate"
when
$avg : Number() from accumulate(Sensor(temp >= 5 && $temp : temp),average($temp))
then
System.out.println("accumulate成功執(zhí)行,平均溫度為:" + $avg);
end
新建測試方法
@Test
public void accumulate() {
session.insert(new Sensor("達(dá)", 8.26));
session.insert(new Sensor("秋", 7.12));
session.insert(new Sensor("春", 3.24));
session.insert(new Sensor("夏", 6.32));
session.insert(new Sensor("冬", 12.23));
session.insert(new Sensor("金", 10.8));
session.fireAllRules();//執(zhí)行規(guī)則
}
執(zhí)行測試,觸發(fā)規(guī)則并打印平均值
accumulate成功執(zhí)行,平均溫度為:8.946
2.5.4 自定義 accunmulate
- init 初始化變量
- action 每次遍歷執(zhí)行的動(dòng)作
- reverse (可選)反轉(zhuǎn)動(dòng)作,用于優(yōu)化
- result 返回的執(zhí)行結(jié)果
@Test
public void diyaccumulate() {
session.insert(new People(1, "達(dá)",26,"diyaccumulate"));
session.insert(new People(0, "秋",18,"diyaccumulate"));
session.insert(new People(0, "春",38,"diyaccumulate"));
session.insert(new People(1, "夏",90,"diyaccumulate"));
session.insert(new People(0, "冬",55,"diyaccumulate"));
session.insert(new People(3, "金",12,"diyaccumulate"));
session.fireAllRules();//執(zhí)行規(guī)則
}
rule "diyaccumulate"
when
People(drlType == "diyaccumulate")
$avg: Number() from accumulate(People($age: age,drlType == "diyaccumulate"),
init(int $total = 0, $count = 0;),
action($total += $age; $count++;),
result($total/$count))
then
System.out.println("Avg: " + $avg);
end
輸出結(jié)果
Avg: 39
教程代碼已提交到ytooo-drools,歡迎star
Drools規(guī)則引擎 系列教程(一)SpringBoot整合 & 快速集成上手
Drools規(guī)則引擎 系列教程(三)Drools規(guī)則語法 & RHS動(dòng)作 & header詳解
更多好玩好看的內(nèi)容,歡迎到我的博客交流,共同進(jìn)步????????WaterMin
喜歡聽相聲的朋友,也可以來我的 YouTube,來聽郭老師的相聲????秋釀