1、基本的匹配規則
1.1變量
drools使用匹配的方式對Fact進行比對,
比如
- 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方法
- public static double calculateAccount(Account account) {
- return 100 + account.balance * 1.2;
- }
在規則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數據結構
- $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
- $customer1 : Customer()
- Customer(eval(age == $customer1.getAge() + 10))
和上個例子一樣,只是使用了內置的eval來寫的。
內置eval不能使用this,比如:
- $customer1 : Customer()
- $customer2 : Customer(this != $customer1)
customer1和customer2不是同一個對象實例
使用內置的eval表達式來描述:
- $customer1 : Customer()
- $customer2 : Customer(eval($customer2 != $customer1))
注意,在內置的eval中不能使用this來指代自己。
嵌套訪問
- $customer : Customer()
- Account(this == $customer.accounts[0])
得到所有customer對象中的第一個賬號
如果一個嵌套訪問的對象屬性值更改了,我們使用modify來提示drools屬性改變了。
This
this指向當前的Fact
和集合相關的運算
contains
- $account : Account()
- $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
- $customer : Customer()
- 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()
- then
- modify($account) {
- setBalance((double)($account.getBalance() * 1.2))
- };
- end
insert 插入
向session的Fact中新增一個事實
- insert(new Account())
retract 收回
從session的Fact中移除一個事實
- retract(0)
1.11規則的屬性部分
規則屬性出現在rule和when關鍵字之間,用於修改和增強標准的規則行為。
- rule "rule attribute"
- salience 100
- dialect "mvel"
- no-loop
- when
- //conditons條件部分
- then
- //consquence推論部分
- end
salience
salience是優先級的意思,它可以為負數,salience越高,表明規則的優先級越高,越先被激發。
默認值是0。
no-loop
表明對於每一個Fact實例,該規則只能被激活一次。
dialect
指定方言。
- dialect "mvel"
原文地址:http://einverne.github.io/post/2019/03/drools-syntax.html