drools語法介紹


這里沒有翻譯http://docs.jboss.org/drools/release/6.4.0.Final/drools-docs/html_single/index.html上的內容 而是參考了網上的一些博客,講的很詳細。摘錄了一篇比較好的文章。

具體的使用例子見后面的wiki:

開始語法之前首先要了解一下drools的基本工作過程,通常而言我們使用一個接口來做事情,首先要穿進去參數,其次要獲取到接口的實現執行完畢后的結果,而drools也是一樣的,我們需要傳遞進去數據,用於規則的檢查,調用外部接口,同時還可能需要獲取到規則執行完畢后得到的結果。在drools中,這個傳遞數據進去的對象,術語叫 Fact對象。Fact對象是一個普通的java bean,規則中可以對當前的對象進行任何的讀寫操作,調用該對象提供的方法,當一個java bean插入到workingMemory中,規則使用的是原有對象的引用,規則通過對fact對象的讀寫,實現對應用數據的讀寫,對於其中的屬性,需要提供getter setter訪問器,規則中,可以動態的往當前workingMemory中插入刪除新的fact對象。

規則文件可以使用 .drl文件,也可以是xml文件,這里我們使用drl文件。

規則語法:

package:對一個規則文件而言,package是必須定義的,必須放在規則文件第一行。特別的是,package的名字是隨意的,不必必須對應物理路徑,跟java的package的概念不同,這里只是邏輯上的一種區分。同樣的package下定義的function和query等可以直接使用。

比如:package com.drools.demo.point

import:導入規則文件需要使用到的外部變量,這里的使用方法跟java相同,但是不同於java的是,這里的import導入的不僅僅可以是一個類,也可以是這個類中的某一個可訪問的靜態方法。

比如:

import com.drools.demo.point.PointDomain;

import com.drools.demo.point.PointDomain.getById;

rule:定義一個規則。rule "ruleName"。一個規則可以包含三個部分:

屬性部分:定義當前規則執行的一些屬性等,比如是否可被重復執行、過期時間、生效時間等。

條件部分,即LHS,定義當前規則的條件,如  when Message(); 判斷當前workingMemory中是否存在Message對象。

結果部分,即RHS,這里可以寫普通java代碼,即當前規則條件滿足后執行的操作,可以直接調用Fact對象的方法來操作應用。

規則事例:

rule "name"

       no-loop true

       when

               $message:Message(status == 0)

       then

               System.out.println("fit");

               $message.setStatus(1);

               update($message);

end

上述的屬性中:

no-loop : 定義當前的規則是否不允許多次循環執行,默認是false,也就是當前的規則只要滿足條件,可以無限次執行。什么情況下會出現一條規則執行過一次又被多次重復執行呢?drools提供了一些api,可以對當前傳入workingMemory中的Fact對象進行修改或者個數的增減,比如上述的update方法,就是將當前的workingMemory中的Message類型的Fact對象進行屬性更新,這種操作會觸發規則的重新匹配執行,可以理解為Fact對象更新了,所以規則需要重新匹配一遍,那么疑問是之前規則執行過並且修改過的那些Fact對象的屬性的數據會不會被重置?結果是不會,已經修改過了就不會被重置,update之后,之前的修改都會生效。當然對Fact對象數據的修改並不是一定需要調用update才可以生效,簡單的使用set方法設置就可以完成,這里類似於java的引用調用,所以何時使用update是一個需要仔細考慮的問題,一旦不慎,極有可能會造成規則的死循環。上述的no-loop true,即設置當前的規則,只執行一次,如果本身的RHS部分有update等觸發規則重新執行的操作,也不要再次執行當前規則。

但是其他的規則會被重新執行,豈不是也會有可能造成多次重復執行,數據紊亂甚至死循環?答案是使用其他的標簽限制,也是可以控制的:lock-on-active true

lock-on-active true:通過這個標簽,可以控制當前的規則只會被執行一次,因為一個規則的重復執行不一定是本身觸發的,也可能是其他規則觸發的,所以這個是no-loop的加強版。當然該標簽正規的用法會有其他的標簽的配合,后續提及。

date-expires:設置規則的過期時間,默認的時間格式:“日-月-年”,中英文格式相同,但是寫法要用各自對應的語言,比如中文:"29-七月-2010",但是還是推薦使用更為精確和習慣的格式,這需要手動在java代碼中設置當前系統的時間格式,后續提及。屬性用法舉例:date-expires "2011-01-31 23:59:59" // 這里我們使用了更為習慣的時間格式

date-effective:設置規則的生效時間,時間格式同上。

duration:規則定時,duration 3000   3秒后執行規則

salience:優先級,數值越大越先執行,這個可以控制規則的執行順序。

其他的屬性可以參照相關的api文檔查看具體用法,此處略。

 

規則的條件部分,即LHS部分:

when:規則條件開始。條件可以單個,也可以多個,多個條件一次排列,比如

 when

         eval(true)

         $customer:Customer()

         $message:Message(status==0)

上述羅列了三個條件,當前規則只有在這三個條件都匹配的時候才會執行RHS部分,三個條件中第一個

eval(true):是一個默認的api,true 無條件執行,類似於 while(true)

$message:Message(status==0) 這句話標示的:當前的workingMemory存在Message類型並且status屬性的值為0的Fact對象,這個對象通常是通過外部java代碼插入或者自己在前面已經執行的規則的RHS部分中insert進去的。

前面的$message代表着當前條件的引用變量,在后續的條件部分和RHS部分中,可以使用當前的變量去引用符合條件的FACT對象,修改屬性或者調用方法等。可選,如果不需要使用,則可以不寫。

條件可以有組合,比如:

Message(status==0 || (status > 1 && status <=100))

RHS中對Fact對象private屬性的操作必須使用getter和setter方法,而RHS中則必須要直接用.的方法去使用,比如

  $order:Order(name=="qu")
  $message:Message(status==0 && orders contains $order && $order.name=="qu")

特別的是,如果條件全部是 &&關系,可以使用“,”來替代,但是兩者不能混用

如果現在Fact對象中有一個List,需要判斷條件,如何判斷呢?

看一個例子:

Message {

        int status;

        List<String> names;

}

$message:Message(status==0 && names contains "網易" && names.size >= 1)

上述的條件中,status必須是0,並且names列表中含有“網易”並且列表長度大於等於1

contains:對比是否包含操作,操作的被包含目標可以是一個復雜對象也可以是一個簡單的值。 

Drools提供了十二中類型比較操作符:

>  >=  <  <=  ==  !=  contains / not contains / memberOf / not memberOf /matches/ not matches

not contains:與contains相反。

memberOf:判斷某個Fact屬性值是否在某個集合中,與contains不同的是他被比較的對象是一個集合,而contains被比較的對象是單個值或者對象。

not memberOf:正好相反。

matches:正則表達式匹配,與java不同的是,不用考慮'/'的轉義問題

not matches:正好相反。

 

規則的結果部分

當規則條件滿足,則進入規則結果部分執行,結果部分可以是純java代碼,比如:

then

       System.out.println("OK"); //會在控制台打印出ok

end

當然也可以調用Fact的方法,比如  $message.execute();操作數據庫等等一切操作。

結果部分也有drools提供的方法:

insert:往當前workingMemory中插入一個新的Fact對象,會觸發規則的再次執行,除非使用no-loop限定;

update:更新

modify:修改,與update語法不同,結果都是更新操作

retract:刪除

RHS部分除了調用Drools提供的api和Fact對象的方法,也可以調用規則文件中定義的方法,方法的定義使用 function 關鍵字

function void console {

   System.out.println();

   StringUtils.getId();// 調用外部靜態方法,StringUtils必須使用import導入,getId()必須是靜態方法

}

Drools還有一個可以定義類的關鍵字:

declare 可以再規則文件中定義一個class,使用起來跟普通java對象相似,你可以在RHS部分中new一個並且使用getter和setter方法去操作其屬性。

declare Address
 @author(quzishen) // 元數據,僅用於描述信息

 @createTime(2011-1-24)
 city : String @maxLengh(100)
 postno : int
end

上述的'@'是什么呢?是元數據定義,用於描述數據的數據~,沒什么執行含義

你可以在RHS部分中使用Address address = new Address()的方法來定義一個對象。

其他參考:

 


免責聲明!

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



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