這裏沒有翻譯http://docs.jboss.org/drools/release/6.4.0.Final/drools-docs/html_single/index.html上的內容 而是參考了網上的一些博客,講的很詳細。摘錄了一篇比較好的文章。html
具體的使用例子見後面的wiki:java
開始語法以前首先要了解一下drools的基本工做過程,一般而言咱們使用一個接口來作事情,首先要穿進去參數,其次要獲取到接口的實現執行完畢後的結果,而drools也是同樣的,咱們須要傳遞進去數據,用於規則的檢查,調用外部接口,同時還可能須要獲取到規則執行完畢後獲得的結果。在drools中,這個傳遞數據進去的對象,術語叫 Fact對象。Fact對象是一個普通的java bean,規則中能夠對當前的對象進行任何的讀寫操做,調用該對象提供的方法,當一個java bean插入到workingMemory中,規則使用的是原有對象的引用,規則經過對fact對象的讀寫,實現對應用數據的讀寫,對於其中的屬性,須要提供getter setter訪問器,規則中,能夠動態的往當前workingMemory中插入刪除新的fact對象。正則表達式
規則文件可使用 .drl文件,也能夠是xml文件,這裏咱們使用drl文件。數據庫
規則語法:api
package:對一個規則文件而言,package是必須定義的,必須放在規則文件第一行。特別的是,package的名字是隨意的,沒必要必須對應物理路徑,跟java的package的概念不一樣,這裏只是邏輯上的一種區分。一樣的package下定義的function和query等能夠直接使用。app
好比:package com.drools.demo.pointoop
import:導入規則文件須要使用到的外部變量,這裏的使用方法跟java相同,可是不一樣於java的是,這裏的import導入的不只僅能夠是一個類,也能夠是這個類中的某一個可訪問的靜態方法。post
好比:.net
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()的方法來定義一個對象。
其餘參考: