drools規則語法


1、基本的匹配規則

1.1變量

drools使用匹配的方式對Fact進行比對

比如

MVEL代碼   收藏代碼
  1. account : Account(balance > 100)  

 這個規則的含義就是在Fact中找到類型為Account,且balance屬性值大於100的所有Account實例。

可以指定變量來描述一個類型或者一個映射一個類的屬性

比如

MVEL代碼   收藏代碼
  1. $account : Account($type : type)  

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

MVEL代碼   收藏代碼
  1. $account : Account(balance >100)   
  2. Customer(account == $account)  

 這個就是說要找到一些Custom類型的Fact,且其account屬性必須滿足前面定義的balance>100的條件。

1.2類型

drools支持各種java數據類型

String:字符串

MVEL代碼   收藏代碼
  1. Customer(name == "john")  

正則表達式:

 

MVEL代碼   收藏代碼
  1. Customer(name matches "[A-Z][a-z]+")  

 

表示Customer類型的name屬性必須滿足首字母為大寫A-Z,且第二位以后有一個或者多個小寫的a-z組成。

Date:日期類型

MVEL代碼   收藏代碼
  1. Account(dateCreate > "01-Feb-2009")  

 

日期的格式默認是"dd-mmmm-yyyy",可以更改。

Boolean:布爾類型

MVEL代碼   收藏代碼
  1. Transaction(isApprove == true)  

 

Enum:枚舉類型

MVEL代碼   收藏代碼
  1. Account(type == Account.Type.STUDENT)  

 

1.3注釋

單行注釋://或者#

多行注釋: /*   */

1.4包

MVEL代碼   收藏代碼
  1. package com.kingsun.drools.rules  

 

聲明該規則文件所屬的包,是一種namespace組織方式,和java的包類似,物理上不需要存在相應的目錄結構,它只是邏輯上的划分。

1.5導入

import可以導入在規則中使用到的類,也可以導入在規則中使用到的外部定義的functiong

MVEL代碼   收藏代碼
  1. import java.util.Map;  
  2.   
  3. import com.kingsun.drools.service.LegacyBankService.extractData;  

 

導入方法時,這個方法必須是static的,因為利用的是jdk1.5的static import特性。

1.6全局變量global

聲明一個global變量

MVEL代碼   收藏代碼
  1. global ReportFactory reportFactory;  

 

給全局變量賦值

MVEL代碼   收藏代碼
  1. session.setGlobal("reportFactory", reportFactory);  

 

或者

MVEL代碼   收藏代碼
  1. List<Command> commands = new ArrayList<Command>();  
  2.   
  3. commmands.add(CommandFactory.newSetGlobal("reportFactory", reportFactory));  

 使用全局變量

MVEL代碼   收藏代碼
  1. session.getGlobals();  

 

1.7函數Functions

function可以在規則文件中定義,但更多的是使用外部類中定義的static方法,這樣只要java中可以實現的邏輯,在規則中都可以做為function調用。

調用外部類的functiong需要注意的是方法必須是靜態的,static,而且這個類可以在Help輔助類中定義。

外部類需要import,此時在function中用到的參數類型也需要import。

如: 在外部的ValidationHelper輔助類中定一個一個static方法

Java代碼   收藏代碼
  1. public static double calculateAccount(Account account) {  
  2.   
  3.     return 100 + account.balance * 1.2;  
  4.   
  5. }  

 

在規則drl文件中可以這么使用:

Drl代碼   收藏代碼
  1. import com.kingsun.drools.domain.Account;  
  2.   
  3. import function com.kingsun.drools.util.ValidationHelper.calculateAccount;  
  4.   
  5. rule "validation account"  
  6.   
  7.     when  
  8.   
  9.         $account : Account(balance > 100)  
  10.   
  11.     then  
  12.   
  13.         Account(balance == calculateAccount($account));  
  14.   
  15. end  

 

 

1.8方言dialect

在規則表達式中可以使用方言來簡化表達式,使之更加具有可讀性。

MVEL代碼   收藏代碼
  1. package com.kingsun.drools.rules;  
  2.   
  3. dialect "mvel"  

 

方言默認的是java,drools也支持mvel,在package的后面聲明該規則文件使用的方言

 mvel

   mvel是一種基於java應用程序的表達式語言,它支持屬性和方法的直接訪問

    簡單屬性表達式:

        

MVEL代碼   收藏代碼
  1. ($customer.name == "john") && (balance > 100)   

    滿足姓名為“john”,且balance必須大於100的customer

         支持屬性導航:

               Bean屬性導航

        

MVEL代碼   收藏代碼
  1. $customer.address.postalCode = "123" 等同於 $customer.getAddress().setPostalCode("123")  

 

              訪問List數據結構

        

MVEL代碼   收藏代碼
  1. $customer.accounts[3] 等同於 $customer.getAccounts(3)  

              訪問Map數據結構

        

MEVL代碼   收藏代碼
  1. $customerMap["123"] 等同於$customerMap.get["123"]  

        內置的List、Map和數組arrays

               Map:創建一個AccountMap實例-->

MEVL代碼   收藏代碼
  1. ["001", new Account("001"), "002", new Account("002")]  

 等同於創建了一個Map,並向Map中put了兩個entry。

               List:創建一個List實例-->

MEVL代碼   收藏代碼
  1. ["001", "002", "003"]   

 等同於創建了一個List,並向List中add了三個對象。

              Arrays:創建一個數組-->

MEVL代碼   收藏代碼
  1. {"001", "002", "003"}  

          等同於創建了一個Array,並初始化了三個成員。

      嵌套

       使用這個可以方便的訪問復雜對象中包括的集合類型的對象。

           

MVEL代碼   收藏代碼
  1. listOfPostCode = (postCode in (addresses in $customerS))  

     這個得到一個postCode列表,它是customers集合中的每一個custemer對象的地址屬性中包含的postCode信息的匯集。

      強制轉換

      當使用array = {1, 2, 3}時,mvel會自動將元素轉換成integer類型。

      返回值

      保存變量的值等於最后一次賦予的值。

      mvel同時還支持方法調用、控制流、賦值、動態類型等等,使用mvel的性能很好,不過要小心使用。在drools中有一些核心特性就是通過mvel來實現的。

1.9規則的條件部分

 And 與

MVEL代碼   收藏代碼
  1. $customer : Customer(name == "john", age > 20)  

 
在condition中使用換行來表示與

OR 或

 

MVEL代碼   收藏代碼
  1. $customer : Customer(name == "john" || age > 20)  

 

 Not 非

MVEL代碼   收藏代碼
  1. not Account(type == Account.Type.STUDENT)   

表示所有賬戶類型不是STUDENT的賬戶

 

exists 存在

MVEL代碼   收藏代碼
  1. exists Account(type == Account.Type.STUDENT)  

 

Eval

捕獲異常,只要eval表達式中的結果為true或者false就可以

MVEL代碼   收藏代碼
  1. $account : Account()  
  2.   
  3. eval(accountService.isUniqueAccountNumber($account))  

 

返回值約束

MEVL代碼   收藏代碼
  1. $customer1 : Customer()  
  2.   
  3. Customer(age == ($customer.getAge + 10))  

 

內置eval

MEVL代碼   收藏代碼
  1. $customer1 : Customer()  
  2.   
  3. Customer(eval(age == $customer1.getAge() + 10))  

和上個例子一樣,只是使用了內置的eval來寫的。

內置eval不能使用this,比如:

MEVL代碼   收藏代碼
  1. $customer1 : Customer()  
  2.   
  3. $customer2 : Customer(this != $customer1)  

 

customer1和customer2不是同一個對象實例

使用內置的eval表達式來描述:

MVEL代碼   收藏代碼
  1. $customer1 : Customer()  
  2.   
  3. $customer2 : Customer(eval($customer2 != $customer1))  

 

注意,在內置的eval中不能使用this來指代自己。

嵌套訪問

MVEL代碼   收藏代碼
  1. $customer : Customer()  
  2.   
  3. Account(this == $customer.accounts[0])  

 

得到所有customer對象中的第一個賬號

如果一個嵌套訪問的對象屬性值更改了,我們使用modify來提示drools屬性改變了。

This

this指向當前的Fact

 

和集合相關的運算

contains

MVEL代碼   收藏代碼
  1. $account : Account()  
  2.   
  3. $customer : Customer(accounts contains $account)  
  4.   
  5. $customer : Customer(accounts not contains $account)  

 

member of

MVEL代碼   收藏代碼
  1. $customer : Customer($accounts : accounts)  
  2.   
  3. Account(this member of $accounts)  
  4.   
  5. 或  
  6.   
  7. Account(this member of $customer.accounts)  

 

From

MVEL代碼   收藏代碼
  1. $customer : Customer()  
  2.   
  3. Account() from $customer.accounts  

 

from可以接受service的方法調用后的結果集,也可以指向一個對象或者一個集合

 

1.10規則的推理部分

規則引擎的作用就是在於根據預先制定的規則去和事實匹配,對符合激發條件的規則,執行規則中定義的推理,作出相應的處理。

有時候,規則和規則之間存在沖突,drools使用沖突解決策略來解決矛盾。有兩種辦法:一個是設置規則的優先級,優先級高的先觸發。另一個是

在推理部分不推薦使用if then這樣的條件判斷語句,它應該是明確的行為,因為條件判斷應該在LHS中就已經明確區分出來了,如果推論部分存在條件判斷的話,應該增加新的規則以滿足要求。這樣做符合最佳實踐。

當一個規則被激活,並且推理部分被執行,它可能會對Fact做一些修改或者更新,這樣的修改和更新可能會激活更多的其他規則,因此,必須在推論部分明確指出這個規則對Fact作出的更新和修改,Drools能夠及時對Fact進行更新,這樣其他規則才能及時應用到最新的Fact數據上來。

推論部分經常使用的幾個函數

modify 修改

更新session中存在的Fact

MVEL代碼   收藏代碼
  1. rule "interst calculation"  
  2.   
  3. no-loop  
  4.   
  5.     when   
  6.   
  7.         $account : Account()  
  8.   
  9.     then  
  10.   
  11.         modify($account) {  
  12.   
  13.             setBalance((double)($account.getBalance() * 1.2))  
  14.   
  15.         };  
  16.   
  17. end  

 

insert 插入

向session的Fact中新增一個事實

MVEL代碼   收藏代碼
  1. insert(new Account())  

 

retract 收回

從session的Fact中移除一個事實

MEVL代碼   收藏代碼
  1. retract(0)  

 

1.11規則的屬性部分

規則屬性出現在rule和when關鍵字之間,用於修改和增強標准的規則行為。

MVEL代碼   收藏代碼
  1. rule "rule attribute"  
  2.   
  3. salience 100  
  4.   
  5. dialect "mvel"  
  6.   
  7. no-loop  
  8.   
  9.     when       
  10.   
  11.         //conditons條件部分  
  12.   
  13.     then  
  14.   
  15.         //consquence推論部分  
  16.   
  17. end  

 

salience

salience是優先級的意思,它可以為負數,salience越高,表明規則的優先級越高,越先被激發。

默認值是0。

no-loop

表明對於每一個Fact實例,該規則只能被激活一次。

dialect

指定方言。

MVEL代碼   收藏代碼
  1. dialect "mvel"  

 

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM