说说 jBPM 流程定义语言(4)—— decision 活动 (判断活动)

根据条件在多个流转路径中选择其中一条路径通过,也就是做一个决定性的判断,这时候就可以使用 decision 活动。
decision 活动可以拥有多个流出转移,当流程实例到达 decision 活动时,会根据最先匹配成功的一个条件自动地通过相应的路径。

在 decision 活动中可以使用以下三种方法来判断需要流向哪一个流出路径。

1 使用 decision 活动的 condition 元素

decision 活动中会运行并判断其中的每一个 transition 元素里的流转条件(condition元素)。当遇到一个 transition 元素的 condition 值为 true 或者是一个没有设置 condition 值的 transition 元素,这时流程就会立即转向这个 transition 元素。

decision 活动的 condition 元素属性:

属性类型默认值是否必需描述
expr表达式必需描述转移条件的表达式
lang表达式的语言名称脚本引擎配置文件(jbpm.default.scriptmanager.xml)中定义的默认表达式语言名称,默认为 jUEL,即 EL 表达式语言可选转移条件表达式的语言类型

举个例子:

流程定义如下:

<?xml version="1.0" encoding="UTF-8"?>

<process key="DecisionConditions" name="DecisionConditions" xmlns="http://jbpm.org/4.4/jpdl">
   <start g="301,169,48,48" name="start1">
      <transition to="exclusive1"/>
   </start>
   <decision g="417,165,48,48" name="exclusive1">
      <transition g="441,103:" to="提交文档">
      	<condition expr="#{content=='good'}"/>
      </transition>
      <transition to="再试一次">
      	<condition expr="#{content=='bad'}"/>
      </transition>
      <transition g="443,282:" to="放弃"/>
   </decision>
   <state g="556,78,167,52" name="提交文档"/>
   <state g="563,166,92,52" name="再试一次"/>
   <state g="570,258,92,52" name="放弃"/>
</process>

测试:

Map<String,Object> variables=new HashMap<String,Object>();
variables.put("content","good");

//发起实例并传入变量
ProcessInstance processInstance = executionService.startProcessInstanceByKey
		("DecisionConditions",variables);

//断言流程实例流向了 “提交文档”
assertTrue(processInstance.isActive("提交文档"));

2 使用 decision 活动的 expr 属性

可以利用 decision 活动本身的 expr(表达式)属性来决定流程的转向。decision 活动的 expr 属性值可以直接返回字符串类型的流出转移名称,来指定需要转移的路径。

decision 活动支持的属性:

属性类型默认值是否必需描述
expr表达式必需描述转移名称的表达式
lang表达式语言名称脚本引擎配置文件(jbpm.default.scriptmanager.xml)中定义的默认表达式语言名称,默认为 jUEL,即 EL 表达式语言可选指定转移条件表达式语言的类型

举个例子:

流程定义如下:

<?xml version="1.0" encoding="UTF-8"?>

<process key="DecisitonExpression" name="DecisitonExpression" xmlns="http://jbpm.org/4.4/jpdl">
   <start g="309,137,48,48" name="start1">
      <transition to="exclusive1"/>
   </start>
   <decision expr="#{content}" g="417,136,48,48" name="exclusive1">
      <transition g="443,100:60,-22" name="好" to="提交文档"/>
      <transition g="-9,-22" name="坏" to="再试一次"/>
      <transition g="445,240:53,-22" name="糟糕" to="放弃"/>
   </decision>
   <state g="566,77,167,52" name="提交文档"/>
   <state g="570,143,92,52" name="再试一次"/>
   <state g="570,221,92,52" name="放弃"/>
</process>

测试:

Map<String,Object> variables=new HashMap<String,Object>();
variables.put("content","好");

//发起实例并传入变量
ProcessInstance processInstance = executionService.startProcessInstanceByKey
		("DecisitonExpression",variables);

//断言流程实例流向了 “提交文档”
assertTrue(processInstance.isActive("提交文档"));

3 使用 decision 活动的 handler 元素

如果需要在判断流程时计算大量、复杂的业务逻辑,那么,可以自己实现判断处理接口,即通过 decision handler 的方式来实现。

首先,必须实现 DecisionHandler 接口,将流转判断的决定权委派给这个实现类。这个接口定义如下:

/** interface for supplying user programmed decisions.
 * 
 * @author Tom Baeyens */
public interface DecisionHandler extends Serializable {

//接口定义了一个唯一的方法,提供流程实例的执行上下文(execution)作为参数,需要返回字符串型的转移名称  
  /** the name of the selected outgoing transition */ 
  String decide(OpenExecution execution);
}

这个 handler 是作为 decision 活动的子元素被配置的。

这里的流程图表面上看,与 “使用 decision 活动的 expr 属性” 小节的流程图一样,但这里内部定义中使用的是 handler。

流程定义:

<?xml version="1.0" encoding="UTF-8"?>

<process key="DecisionHandler" name="DecisionHandler" xmlns="http://jbpm.org/4.4/jpdl">
   <start g="309,137,48,48" name="start1">
      <transition to="exclusive1"/>
   </start>
   <decision g="417,136,48,48" name="exclusive1">
      <!-- 所有的流程判断逻辑都委托给了这个 ContentEvaluation 类统一处理-->
   	  <handler class="net.deniro.jbpm.test.ContentEvaluation" />
      <transition g="439,104:54,-23" name="好" to="提交文档"/>
      <transition g="-16,-23" name="坏" to="再试一次"/>
      <transition g="444,233:47,-23" name="糟糕" to="放弃"/>
   </decision>
   <state g="566,77,167,52" name="提交文档"/>
   <state g="567,133,92,52" name="再试一次"/>
   <state g="574,210,92,52" name="放弃"/>
</process>

判断处理器 ContentEvaluation:

public class ContentEvaluation implements DecisionHandler {
    @Override
    public String decide(OpenExecution execution) {
        //获取流程变量
        String content = (String) execution.getVariable("content");

        if (content.equals("你很棒")) {
            return "好";
        }
        if (content.equals("你需要努力")) {
            return "坏";
        }

        //上述条件都不满足,就流向 ugly
        return "糟糕";
    }
}

测试代码:

Map<String,Object> variables=new HashMap<String,Object>();
variables.put("content","你很棒");

//发起实例并传入变量
ProcessInstance processInstance = executionService.startProcessInstanceByKey
	("DecisionHandler",variables);

//断言流程实例流向了 submit document
assertTrue(processInstance.isActive("提交文档"));

decision 活动 和 state 活动都能实现条件流转,这两种方式有何区别,在实际业务应用中该选择何种方式呢?

  • 如果 decision 活动定义的流转条件没有任何一个得到满足,那么流程实例将无法进行下去,会抛出异常。
  • 如果 state 活动有多个流出转移,且同样没有任何一个得到满足,那么流程实例将流向 state 活动定义的第一条流出转移,从而进行下去。

因此,decision 活动具有更加严格的条件判断特性,如果不定义默认路径,则没有条件得到满足,也就会直接抛错哦O(∩_∩)O~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值