SpringBoot整合 drools規則引擎 系列教程(二)Drools規則語法 & LHS 條件

SpringBoot整合 drools規則引擎 系列教程(一)快速集成上手java

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

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

1. .drl文件結構

  • package 包充當每組規則的惟一名稱空間。一個規則庫能夠包含多個程序包。

一般,將包的全部規則與包聲明存儲在同一文件中,以便包是獨立的。可是,
也能夠在規則中使用從其餘的包中導入的對象github

  • imports 與Java中的import語句相似,用來標識在規則中使用的任何對象的標準路徑和類型名稱
  • factions 函數代碼塊如:
function String hello(String applicantName) {
    return "Hello " + applicantName + "!";
}
  • queries 在Drools引擎的工做內存中搜索與DRL文件中的規則相關的事實
query "people under the age of 21"
    $person : Person( age < 21 )
end
  • global 爲規則提供數據或服務
  • rules 規則

2.rules 規則

2.1 規則屬性

2.1.1 規則屬性是能夠添加到業務規則以修改規則行爲的其餘規範
屬性 描述
salience 定義規則優先級的整數
enabled 規則啓用開關
date-effective 包含日期和時間定義的字符串。僅噹噹前日期和時間在date-effective屬性以後時,才能激活該規則。
date-expires 若是當前日期和時間在date-expires屬性以後,則沒法激活該規則。
no-loop 選擇該選項後,若是規則的結果從新觸發了先前知足的條件,則沒法從新激活(循環)規則。若是未選擇條件,則在這些狀況下能夠循環規則。
agenda-group 標識要向其分配規則的議程組
activation-group 激活組,在激活組中,只能激活一個規則。觸發的第一個規則將取消激活組中全部規則的全部未決激活。
duration 定義了若是仍知足規則條件,則能夠激活規則的持續時間(以毫秒爲單位)。
timer cron定時表達式
calendar 時鐘
auto-focus 僅適用於議程組中的規則。選擇該選項後,下次激活該規則時,將自動將焦點分配給分配了該規則的議程組。
lock-on-active no-loop屬性的更強版
ruleflow-group 標識規則流組的字符串
dialect 用於標識規則中的代碼表達式JAVA或MVEL將其用做語言

2.2 匹配模式

2.2.1 沒有約束的匹配模式

實事不須要知足任何條件,若類型相同,則觸發該規則,如:正則表達式

package com.ytooo.bean
import com.ytooo.bean.People
dialect  "java"

rule "girl"
    when
        People()
    then
        System.out.println("girl規則執行");
end
2.2.2 有條件約束的匹配模式

實事類型相同,且知足條件,則觸發該規則,如:segmentfault

package com.ytooo.bean
import com.ytooo.bean.People
dialect  "java"

rule "girl"
    when
        People(sex == 0 && drlType == "people")
    then
        System.out.println("girl規則執行");
end
2.2.3 匹配並綁定屬性以及實事

實事類型相同,且知足條件,則觸發該規則,並綁定數據,如:安全

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規則執行");
        System.out.println($p);
        System.out.println($sex);
end

2.3 條件

and,or 等結合規則條件的多個模式,沒有定義關鍵字連詞,默認是and:session

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規則執行");
end

2.4 約束

  標準Java運算符優先級適用於DRL中的約束運算符,而drl運算符除==和!=運算符外均遵循標準Java語義。app

在drl中 Person( firstName != "John" )相似於 !java.util.Objects.equals(person.getFirstName(), "John")函數

約束 描述
!. 使用此運算符能夠以空安全的方式取消引用屬性。!.運算符左側的值不能爲null(解釋爲!= null)
[] 按List索引訪問值或Map按鍵訪問值
<,<=,>,>= 在具備天然順序的屬性上使用這些運算符
==, != 在約束中使用這些運算符做爲equals()和!equals()方法
&&,|| 組合關係條件
matches,not matches 使用這些運算符能夠指示字段與指定的Java正則表達式匹配或不匹配
contains,not contains 使用這些運算符能夠驗證Array或字段是否包含或不包含指定值
memberOf,not memberOf 使用這些運算符能夠驗證字段是否爲定義爲變量Array的成員
soundslike 使用英語發音來驗證單詞是否具備與給定值幾乎相同的聲音(相似於該matches運算符)
in,notin 使用這些運算符能夠指定一個以上的可能值來匹配約束(複合值限制)
2.4.1 約束demo

  來自官方文檔oop

  • 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 取集合中的元素
2.5.1.1 新建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;

}
2.5.1.2 新建 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
2.5.1.3 新建測試方法
@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();//執行規則
}
2.5.1.4 執行測試,在三組數據中,2個people知足條件,執行兩次
People(sex=0, name=秋, drlType=from)
People(sex=1, name=達, drlType=from)
2.5.2 collect

  從指定來源或從Drools引擎的工做內存中獲取集合,可使用Java集合(例如List,LinkedList和HashSet)

2.5.2.1 新建 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執行成功,匹配結果爲:"+$alarms);
    end
2.5.2.2 新建測試方法
@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();//執行規則
}
2.5.1.4 執行測試,正確打印出匹配的實事,其中 sex=3的「金」 沒有匹配到結果中
collect執行成功,匹配結果爲:
[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)]

  當改變參數,入參只留下兩個 sex != 3 的數據,則沒有任何打印結果

2.5.3 accumulate 迭代器

  用於遍歷數據集對數據項執行自定義或預設動做並返回結果。

2.5.3.1 accumulate 函數
  • average
  • min
  • max
  • count
  • sum
  • collectList 獲取列表
  • collectSet 獲取集合
2.5.3.2 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成功執行,平均溫度爲:" + $avg);
end
2.5.3.3 新建測試方法
@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();//執行規則
}
2.5.3.4 執行測試,觸發規則並打印平均值
accumulate成功執行,平均溫度爲:8.946
2.5.3.5 自定義 accunmulate
  • init 初始化變量
  • action 每次遍歷執行的動做
  • reverse (可選)反轉動做,用於優化
  • result 返回的執行結果
@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();//執行規則
}
rule "diyaccumulate"
    when
        $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
輸出結果
Avg: 39

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

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

相關文章
相關標籤/搜索