疯狂Activiti6.0连载(15)DMN规则匹配表达式

  本文节选自《疯狂工作流讲义(第2版)》

京东购买地址:https://item.jd.com/12246565.html

工作流Activiti6电子书http://blog.****.net/boxiong86/article/details/78488562

工作流Activiti6教学视频http://blog.****.net/boxiong86/article/details/78608585

DMN规则匹配表达式

规则引擎中的输入参数与输出结果,可以在inputExpression元素下使用MVEL表达式,这样就意味着在规则匹配以及结果处理上,都使得规则引擎变得很灵活,本小节将以MVEL为基础,讲述Activiti规则引擎在匹配上的原理。

MVEL表达式简介

MVEL一款基于Java程序的表达式语言,它支持大部分的Java语法,当前版本为2.0使用MVEL,可以在XML文档实现获取属性值、进行运算、设置结果等功能,除此之外,还可以对其进行扩展,实现更为复杂的需求。目前很多开源项目都使用了MVEL表达式,例如DroolsApache Camel等框架。Activiti规则引擎中也使用了MVEL,因此允许在DMN文件使用跟以下代码片断类似的表达式:

person.name == Angus && person.age == 30

以上表达式判断person对象的name属性值是否为“Angus”以及age属性值是否为30表达式的执行结果为true或者false本小节将先讲述MVEL简单使用。

执行第一个表达式

下面编写一个最简单的表式,使用MVELAPI进行编译与执行,见代码清单15-13

代码清单15-13codes\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粗体字代码,使用了MVELAPI进行表达式编译和执行。先编译了“personName == Angus”的表达式,表示personName这个运行参数的值是否为“Angus”,在运行时,传入参数Map即可。代码清单15-13执行了两次表达式,第一次执行结果为true,第二次传入了不等的参数,因此执行结果为false。运行代码清单15-13,输出结果如下:

表达式第一次执行结果:true

表达式第二次执行结果:false

使用对象执行表达式

MVEL表达式中,也支持传入对象,并可以获取对象的值或者方法返回值来进行运算,代码清单15-14中的表达式,使用了Java对象。

代码清单15-14codes\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”,并且personage属性值为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-15codes\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.****.net/boxiong86/article/details/78488226

工作流Activiti6教学视频http://blog.****.net/boxiong86/article/details/78608585

疯狂Activiti6.0连载(15)DMN规则匹配表达式

疯狂Activiti6.0连载(15)DMN规则匹配表达式