本文節選自《瘋狂工作流講義(第2版)》
京東購買地址:https://item.jd.com/12246565.html
工作流Activiti6電子書:http://blog.csdn.net/boxiong86/article/details/78488562
工作流Activiti6教學視頻:http://blog.csdn.net/boxiong86/article/details/78608585
DMN規則匹配表達式
規則引擎中的輸入參數與輸出結果,可以在inputExpression元素下使用MVEL表達式,這樣就意味着在規則匹配以及結果處理上,都使得規則引擎變得很靈活,本小節將以MVEL爲基礎,講述Activiti規則引擎在匹配上的原理。
MVEL表達式簡介
MVEL是一款基於Java程序的表達式語言,它支持大部分的Java語法,當前版本爲2.0。使用MVEL,可以在XML文檔中實現獲取屬性值、進行運算、設置結果等功能,除此之外,還可以對其進行擴展,實現更爲複雜的需求。目前很多開源項目都使用了MVEL表達式,例如Drools、Apache Camel等框架。Activiti規則引擎中也使用了MVEL,因此允許在DMN文件使用跟以下代碼片斷類似的表達式:
person.name == ‘Angus’ && person.age == 30
以上表達式判斷person對象的name屬性值是否爲“Angus”以及age屬性值是否爲30,表達式的執行結果爲true或者false。本小節將先講述MVEL的簡單使用。
執行第一個表達式
下面編寫一個最簡單的表式,使用MVEL的API進行編譯與執行,見代碼清單15-13。
代碼清單15-13:codes\15\15.5\mvel-test\src\org\crazyit\activiti\FirstTest.java
//進行編譯
Serializable compiledExpression = MVEL
.compileExpression("personName == 'Angus'");
//設置執行參數
Map<String, String> params = new HashMap<String, String>();
params.put("personName", "Angus");
//執行表達式並返回結果
Boolean result = MVEL.executeExpression(compiledExpression, params,
Boolean.class);
//控制檯輸出結果
System.out.println("表達式第一次執行結果:" + result);
//傳入其他 參數,結果將爲false
params.put("personName", "Paris");
//再次執行表達式
result = MVEL.executeExpression(compiledExpression, params,
Boolean.class);
//輸出結果
System.out.println("表達式第二次執行結果:" + result);
代碼清單15-13的粗體字代碼,使用了MVEL的API進行表達式編譯和執行。先編譯了“personName == ‘Angus’”的表達式,表示personName這個運行參數的值是否爲“Angus”,在運行時,傳入參數Map即可。代碼清單15-13執行了兩次表達式,第一次執行結果爲true,第二次傳入了不等的參數,因此執行結果爲false。運行代碼清單15-13,輸出結果如下:
表達式第一次執行結果:true
表達式第二次執行結果:false
使用對象執行表達式
MVEL表達式中,也支持傳入對象,並可以獲取對象的值或者方法返回值來進行運算,代碼清單15-14中的表達式,使用了Java對象。
代碼清單15-14:codes\15\15.5\mvel-test\src\org\crazyit\activiti\ObjectTest.java
//進行編譯
Serializable compiledExpression = MVEL
.compileExpression("person.name == 'Angus' && person.age == 30");
//設置執行參數
Map<String, Object> params = new HashMap<String, Object>();
//設置名稱與年齡均符合條件
Person p = new Person();
p.setName("Angus");
p.setAge(30);
params.put("person", p);
//執行表達式並返回結果,輸出爲true
Boolean result = MVEL.executeExpression(compiledExpression, params,
Boolean.class);
System.out.println("第一次執行表達式結棍:" + result);
//修改參數年齡
Person p2 = new Person();
p2.setName("Angus");
p2.setAge(20);
params.put("person", p2);
//重新執行表達式,結果false
result = MVEL.executeExpression(compiledExpression, params,
Boolean.class);
System.out.println("第二次執行表達式結果:" + result);
代碼清單15-14中,執行的表達式爲,person實例的name屬性值是否爲“Angus”,並且person的age屬性值爲30,這兩個條件都符合時,表達式返回true。代碼清單15-14中的粗體字代碼,分別執行了兩次表達,第一次的參數完全符合條件,第二次執行的參數age不符合條件,最終輸出false。執行代碼清單15-14,輸出結果如下:
第一次執行表達式結棍:true
第二次執行表達式結果:false
規則引擎規則匹配邏輯
在DMN文件中定義規則的輸入參數和輸出結果的時候,可以在text元素下面寫入MVEL表達式,以下代碼片斷爲rule元素定義:
<rule>
<inputEntry id="inputEntry1">
<text>
<![CDATA[
執行匹配的MVEL表達式
]]>
</text>
</inputEntry>
<outputEntry id="outputEntry1">
<text>
<![CDATA[
處理輸出結果的MVEL表達式
]]>
</text>
</outputEntry>
</rule>
以上代碼片斷的粗體字代碼,在inputEntry下的text元素,可以使用MVEL表達式,但要注意的是,該表達式的結果必須爲Boolean類型,因爲該表達式決定規則是否匹配。在outputEntry下的text元素,同樣可添加MVEL表達式,該表達式的計算結果就是規則的返回結果,注意要與決策表的輸出結果類型相匹配,請見以下代碼片斷:
<output id="outputId" label="Output 1" name="myResult"typeRef="number" />
<rule>
<inputEntry id="inputEntry1">
<text>
<![CDATA[
執行匹配的MVEL表達式
]]>
</text>
</inputEntry>
<outputEntry id="outputEntry1">
<text>
<![CDATA[
輸出結果的MVEL表達式,要返回數字
]]>
</text>
</outputEntry>
</rule>
以上代碼片斷的粗體字代碼,定義了輸出結果的類型爲“number”,如果匹配到的規則,輸出結果的MVEL表達返回的是字符串,則會報出異常。
Activiti規則引擎在讀取inputEntry配置的MVEL表達式時,會進處理,將輸入參數的名稱添加到配置的MVEL表達式前面,組合成新的表達式讓MVEL去執行,在組合成新的表達式時,會有兩種處理方式,請見代碼清單15-15。
代碼清單15-15:codes\15\15.5\dmn-mvel\resource\dmn\GetExpression.dmn
<rule>
<inputEntry id="inputEntry1">
<text>
<!--生成的表達式爲personName.equals('Angus') -->
<![CDATA[
.equals('Angus')
]]>
</text>
</inputEntry>
</rule>
<rule>
<inputEntry id="inputEntry2">
<text>
<!--生成的表達式爲 personName == 'Angus' -->
<![CDATA[
== 'Angus'
]]>
</text>
</inputEntry>
</rule>
代碼清單15-15中定義了兩個規則,第一個規則定義的MVEL表達式爲“.equals”,此種情況下,Activiti會自動生成“personName.equals”這樣的語句,personName是輸入參數的名稱。第二個規則定義的表達式爲“==‘Angus’”,則Activiti會自動生成“personName == ‘Angus’”,即自動加上參數名稱與一個空格。對比這兩種情況可知,Activiti會根據我們定義的表達式是否以“.”(點)開頭,然後分別作兩種處理。在寫規則的MVEL表達式時,要注意這個細節。
本文節選自《瘋狂Workflow講義(第2版)》
京東購買地址:https://item.jd.com/12246565.html
工作流Activiti6電子書:http://blog.csdn.net/boxiong86/article/details/78488226
工作流Activiti6教學視頻:http://blog.csdn.net/boxiong86/article/details/78608585