1、基本的比對規則
1.1變量
drools使用比對的方式對Fact進行比對,
比如
MVEL代碼

- account : Account(balance > 100)
這個規則的含義就是在Fact中找到類型為Account,且balance屬性值大于100的所有Account執行個體。
可以指定變量來描述一個類型或者一個映射一個類的屬性,

- $account : Account($type : type)
使用$Variable來定義一個變量,這裡定義了兩個變量,$account表示定義一個類型為Account的變量,而$type映射Account類型中的type屬性。定義變量是為了在後續的規則中使用。

- $account : Account(balance >100)
- Customer(account == $account)
這個就是說要找到一些Custom類型的Fact,且其account屬性必須滿足前面定義的balance>100的條件。
1.2類型
drools支援各種java資料類型
String:字元串

- Customer(name == "john")
正規表達式:

- Customer(name matches "[A-Z][a-z]+")
表示Customer類型的name屬性必須滿足首字母為大寫A-Z,且第二位以後有一個或者多個小寫的a-z組成。
Date:日期類型

- Account(dateCreate > "01-Feb-2009")
日期的格式預設是"dd-mmmm-yyyy",可以更改。
Boolean:布爾類型

- Transaction(isApprove == true)
Enum:枚舉類型

- Account(type == Account.Type.STUDENT)
1.3注釋
單行注釋://或者#
多行注釋: /* */
1.4包

- package com.kingsun.drools.rules
聲明該規則檔案所屬的包,是一種namespace組織方式,和java的包類似,實體上不需要存在相應的目錄結構,它隻是邏輯上的劃分。
1.5導入
import可以導入在規則中使用到的類,也可以導入在規則中使用到的外部定義的functiong

- import java.util.Map;
- import com.kingsun.drools.service.LegacyBankService.extractData;
當導入方法時,這個方法必須是static的,因為利用的是jdk1.5的static import特性。
1.6全局變量global
聲明一個global變量

- global ReportFactory reportFactory;
給全局變量指派

- session.setGlobal("reportFactory", reportFactory);
或者

- List<Command> commands = new ArrayList<Command>();
- commmands.add(CommandFactory.newSetGlobal("reportFactory", reportFactory));
使用全局變量

- session.getGlobals();
1.7函數Functions
function可以在規則檔案中定義,但更多的是使用外部類中定義的static方法,這樣隻要java中可以實作的邏輯,在規則中都可以做為function調用。
調用外部類的functiong需要注意的是方法必須是靜态的,static,而且這個類可以在Help輔助類中定義。
外部類需要import,此時在function中用到的參數類型也需要import。
如: 在外部的ValidationHelper輔助類中定一個一個static方法
Java代碼

- public static double calculateAccount(Account account) {
- return 100 + account.balance * 1.2;
- }
在規則drl檔案中可以這麼使用:
Drl代碼

- import com.kingsun.drools.domain.Account;
- import function com.kingsun.drools.util.ValidationHelper.calculateAccount;
- rule "validation account"
- when
- $account : Account(balance > 100)
- then
- Account(balance == calculateAccount($account));
- end
1.8方言dialect
在規則表達式中可以使用方言來簡化表達式,使之更加具有可讀性。

- package com.kingsun.drools.rules;
- dialect "mvel"
方言預設的是java,drools也支援mvel,在package的後面聲明該規則檔案使用的方言
mvel
mvel是一種基于java應用程式的表達式語言,它支援屬性和方法的直接通路
簡單屬性表達式:

- ($customer.name == "john") && (balance > 100)
滿足姓名為“john”,且balance必須大于100的customer
支援屬性導航:
Bean屬性導航

- $customer.address.postalCode = "123" 等同于 $customer.getAddress().setPostalCode("123")
通路List資料結構

- $customer.accounts[3] 等同于 $customer.getAccounts(3)
通路Map資料結構
MEVL代碼

- $customerMap["123"] 等同于$customerMap.get["123"]
内置的List、Map和數組arrays
Map:建立一個AccountMap執行個體-->

- ["001", new Account("001"), "002", new Account("002")]
等同于建立了一個Map,并向Map中put了兩個entry。
List:建立一個List執行個體-->

- ["001", "002", "003"]
等同于建立了一個List,并向List中add了三個對象。
Arrays:建立一個數組-->

- {"001", "002", "003"}
等同于建立了一個Array,并初始化了三個成員。
嵌套
使用這個可以友善的通路複雜對象中包括的集合類型的對象。

- listOfPostCode = (postCode in (addresses in $customerS))
這個得到一個postCode清單,它是customers集合中的每一個custemer對象的位址屬性中包含的postCode資訊的彙集。
強制轉換
當使用array = {1, 2, 3}時,mvel會自動将元素轉換成integer類型。
傳回值
儲存變量的值等于最後一次賦予的值。
mvel同時還支援方法調用、控制流、指派、動态類型等等,使用mvel的性能很好,不過要小心使用。在drools中有一些核心特性就是通過mvel來實作的。
1.9規則的條件部分
And 與

- $customer : Customer(name == "john", age > 20)
在condition中使用換行來表示與
OR 或

- $customer : Customer(name == "john" || age > 20)
Not 非

- not Account(type == Account.Type.STUDENT)
表示所有賬戶類型不是STUDENT的賬戶
exists 存在

- exists Account(type == Account.Type.STUDENT)
Eval
捕獲異常,隻要eval表達式中的結果為true或者false就可以

- $account : Account()
- eval(accountService.isUniqueAccountNumber($account))
傳回值限制

- $customer1 : Customer()
- Customer(age == ($customer.getAge + 10))
内置eval

- Customer(eval(age == $customer1.getAge() + 10))
和上個例子一樣,隻是使用了内置的eval來寫的。
内置eval不能使用this,比如:

- $customer2 : Customer(this != $customer1)
customer1和customer2不是同一個對象執行個體
使用内置的eval表達式來描述:

- $customer2 : Customer(eval($customer2 != $customer1))
注意,在内置的eval中不能使用this來指代自己。
嵌套通路

- $customer : Customer()
- Account(this == $customer.accounts[0])
得到所有customer對象中的第一個賬号
如果一個嵌套通路的對象屬性值更改了,我們使用modify來提示drools屬性改變了。
This
this指向目前的Fact
和集合相關的運算
contains

- $customer : Customer(accounts contains $account)
- $customer : Customer(accounts not contains $account)
member of

- $customer : Customer($accounts : accounts)
- Account(this member of $accounts)
- 或
- Account(this member of $customer.accounts)
From

- Account() from $customer.accounts
from可以接受service的方法調用後的結果集,也可以指向一個對象或者一個集合
1.10規則的推理部分
規則引擎的作用就是在于根據預先制定的規則去和事實比對,對符合激發條件的規則,執行規則中定義的推理,作出相應的處理。
有時候,規則和規則之間存在沖突,drools使用沖突解決政策來解決沖突。有兩種辦法:一個是設定規則的優先級,優先級高的先觸發。另一個是
在推理部分不推薦使用if then這樣的條件判斷語句,它應該是明确的行為,因為條件判斷應該在LHS中就已經明确區分出來了,如果推論部分存在條件判斷的話,應該增加新的規則以滿足要求。這樣做符合最佳實踐。
當一個規則被激活,并且推理部分被執行,它可能會對Fact做一些修改或者更新,這樣的修改和更新可能會激活更多的其他規則,是以,必須在推論部分明确指出這個規則對Fact作出的更新和修改,Drools能夠及時對Fact進行更新,這樣其他規則才能及時應用到最新的Fact資料上來。
推論部分經常使用的幾個函數
modify 修改
更新session中存在的Fact

- rule "interst calculation"
- no-loop
- when
- $account : Account()
- modify($account) {
- setBalance((double)($account.getBalance() * 1.2))
- };
insert 插入
向session的Fact中新增一個事實

- insert(new Account())
retract 收回
從session的Fact中移除一個事實

- retract(0)
1.11規則的屬性部分
規則屬性出現在rule和when關鍵字之間,用于修改和增強标準的規則行為。

- rule "rule attribute"
- salience 100
- when
- //conditons條件部分
- //consquence推論部分
salience
salience是優先級的意思,它可以為負數,salience越高,表明規則的優先級越高,越先被激發。
預設值是0。
no-loop
表明對于每一個Fact執行個體,該規則隻能被激活一次。
dialect
指定方言。

原文位址:http://einverne.github.io/post/2019/03/drools-syntax.html