Drools規(guī)則引擎 系列教程(二)Drools規(guī)則語法 & LHS 條件

Drools規(guī)則引擎 系列教程(一)SpringBoot整合 & 快速集成上手

Drools規(guī)則引擎 系列教程(三)Drools規(guī)則語法 & RHS動作 & header詳解

Drools規(guī)則引擎 系列教程(四)Drools 主要API & 決策表

教程代碼已提交到ytooo-drools,歡迎star

文中代碼方法均基于上一篇教程

1. .drl文件結(jié)構(gòu)

  • package 包充當(dāng)每組規(guī)則的唯一名稱空間。一個規(guī)則庫可以包含多個程序包。
    通常,將包的所有規(guī)則與包聲明存儲在同一文件中,以便包是獨立的。但是,
    也可以在規(guī)則中使用從其他的包中導(dǎo)入的對象
  • imports 與Java中的import語句類似,用來標(biāo)識在規(guī)則中使用的任何對象的標(biāo)準(zhǔn)路徑和類型名稱
  • factions 函數(shù)代碼塊如:
function String hello(String applicantName) {
    return "Hello " + applicantName + "!";
}
  • queries 在Drools引擎的工作內(nèi)存中搜索與DRL文件中的規(guī)則相關(guān)的事實
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)先級的整數(shù),數(shù)值越大,優(yōu)先級越高
enabled 規(guī)則啟用開關(guān)
date-effective 包含日期和時間定義的字符串。僅當(dāng)當(dāng)前日期和時間在date-effective屬性之后時,才能激活該規(guī)則。
date-expires 如果當(dāng)前日期和時間在date-expires屬性之后,則無法激活該規(guī)則。
no-loop 選擇該選項后,如果規(guī)則的結(jié)果重新觸發(fā)了先前滿足的條件,則無法重新激活(循環(huán))規(guī)則。如果未選擇條件,則在這些情況下可以循環(huán)規(guī)則。
agenda-group 標(biāo)識要向其分配規(guī)則的議程組
activation-group 激活組,在激活組中,只能激活一個規(guī)則。觸發(fā)的第一個規(guī)則將取消激活組中所有規(guī)則的所有未決激活。
duration 定義了如果仍滿足規(guī)則條件,則可以激活規(guī)則的持續(xù)時間(以毫秒為單位)。
timer cron定時表達式
calendar 時鐘
auto-focus 僅適用于議程組中的規(guī)則。選擇該選項后,下次激活該規(guī)則時,將自動將焦點分配給分配了該規(guī)則的議程組。
lock-on-active no-loop屬性的更強版
ruleflow-group 標(biāo)識規(guī)則流組的字符串
dialect 用于標(biāo)識規(guī)則中的代碼表達式JAVA或MVEL將其用作語言

2.2 匹配模式

2.2.1 沒有約束的匹配模式

實事不需要滿足任何條件,若類型相同,則觸發(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 有條件約束的匹配模式

實事類型相同,且滿足條件,則觸發(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 匹配并綁定屬性以及實事

實事類型相同,且滿足條件,則觸發(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ī)則條件的多個模式,沒有定義關(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ōu)先級適用于DRL中的約束運算符,而drl運算符除==和!=運算符外均遵循標(biāo)準(zhǔn)Java語義。

??在drl中 Person( firstName != "John" )類似于 !java.util.Objects.equals(person.getFirstName(), "John")

約束 描述
!. 使用此運算符可以以空安全的方式取消引用屬性。!.運算符左側(cè)的值不能為null(解釋為!= null)
[] 按List索引訪問值或Map按鍵訪問值
<,<=,>,>= 在具有自然順序的屬性上使用這些運算符
==, != 在約束中使用這些運算符作為equals()和!equals()方法
&&,|| 組合關(guān)系條件
matches,not matches 使用這些運算符可以指示字段與指定的Java正則表達式匹配或不匹配
contains,not contains 使用這些運算符可以驗證Array或字段是否包含或不包含指定值
memberOf,not memberOf 使用這些運算符可以驗證字段是否為定義為變量Array的成員
soundslike 使用英語發(fā)音來驗證單詞是否具有與給定值幾乎相同的聲音(類似于該matches運算符)
in,notin 使用這些運算符可以指定一個以上的可能值來匹配約束(復(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,"達","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個people滿足條件,執(zhí)行兩次
People(sex=0, name=秋, drlType=from)
People(sex=1, name=達, 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, "達","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í)行測試,正確打印出匹配的實事,其中 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=達, drlType=collect)]

??當(dāng)改變參數(shù),入?yún)⒅涣粝聝蓚€ sex != 3 的數(shù)據(jù),則沒有任何打印結(jié)果

2.5.3 accumulate 迭代器

??用于遍歷數(shù)據(jù)集對數(shù)據(jù)項執(zhí)行自定義或預(yù)設(shè)動作并返回結(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("達", 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í)行的動作
  • reverse (可選)反轉(zhuǎn)動作,用于優(yōu)化
  • result 返回的執(zhí)行結(jié)果
@Test
public void diyaccumulate() {
    session.insert(new People(1, "達",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動作 & header詳解





更多好玩好看的內(nèi)容,歡迎到我的博客交流,共同進步????????WaterMin

喜歡聽相聲的朋友,也可以來我的 YouTube,來聽郭老師的相聲????秋釀


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容