本文电子版文档下载
State、Decision 、Task活动详解:
State表示一个等待状态。当流程实例执行到state节点时会暂停下来(处于等待状态),流程的执行会在外部触发器被调用之前一直等待(会暂停)
Decision条件判断节点,表示在多条路径中选择一条。一个 decision 活动拥有很多个传出的转移。流程的执行到达一个 decision 活动时,会自动进行计算来决定采用哪个传出的转移(满足条件时,向下执行,没有符合条件时会停留在decision活动的上一个活动)
Task任务组件,主要用来为流程实例分配任务。通常与form表单相关联.(会暂停下来)
State节点示例
无分支的state节点
流程定义文件:
<?xml version="1.0" encoding="UTF-8"?>
<process name="demo" xmlns="http://jbpm.org/4.3/jpdl">
<start g="134,113,48,48" name="start">
<transition g="-53,-17" name="to state" to="state"/>
</start>
<state g="219,204,92,52" name="state">
<transition g="-41,-17" name="to end" to="end"/>
</state>
<end g="329,301,48,48" name="end"/>
</process>
|
测试代码:
ProcessInstance processInstance=executionService.startProcessInstanceByKey("demo");
System.out.println("流程实例Id:"+processInstance.getId());
System.out.println("流程定义Id:"+processInstance.getProcessDefinitionId());
//判断当前是否位于start节点
System.out.println("是否位于start节点:"+processInstance.isActive("start"));//false
//判断当前是否位于state节点
System.out.println("是否位于state节点:"+processInstance.isActive("state"));//true
//判断流程是否结束
System.out.println("判断流程是否结束:"+processInstance.isEnded());//false
System.out.println("------------------------>使流程继续向下执行");
//使流程继续向下执行
//ProcessInstance instanceState=executionService.signalExecutionById(processInstance.getId());
//此处也可以这么写
ProcessInstance instanceState=executionService.signalExecutionById(processInstance.getId(),"to end");
//to end为流程定义中用于连接state和end节点之间transition的name属性的值
//判断当前是否位于state节点
System.out.println("是否位于state节点:"+instanceState.isActive("state"));//false
//判断流程是否结束
System.out.println("判断流程是否结束:"+instanceState.isEnded());//true
|
执行结果:
流程实例Id:demo.7
流程定义Id:demo-1
是否位于start节点:false
是否位于state节点:true
判断流程是否结束:false
------------------------>使流程继续向下执行
是否位于state节点:false
判断流程是否结束:true
|
有分支的state节点:
注意:在此流程定义中在state节点后含有2个分支(2个transition 即to 400和to 200),那么在使流程实例从state节点向下执行的时候需要明确给出transition的方向name属性的值,否则流程实例会一直处于state节点
executionService.signalExecutionById(processInstance.getId(), "to 200");
流程定义文件:
<?xml version="1.0" encoding="UTF-8"?>
<process name="demo" xmlns="http://jbpm.org/4.3/jpdl">
<start g="347,27,48,48" name="start">
<transition g="-53,-17" name="to state" to="state"/>
</start>
<state g="329,132,92,52" name="state">
<transition name="to 200" to="200" g="-41,-17"/>
<transition name="to 400" to="400" g="-41,-17"/>
</state>
<end g="358,321,48,48" name="end"/>
<state name="200" g="420,226,92,52">
<transition name="to end" to="end" g="-41,-17"/>
</state>
<state name="400" g="266,225,92,52">
<transition name="to end" to="end" g="-41,-17"/>
</state>
</process>
|
测试代码:
ProcessInstance processInstance=executionService.startProcessInstanceByKey("demo");
System.out.println("------------------------>使流程继续向下执行");
System.out.println("------------------------>使流程流向200");
ProcessInstance processInstance200=executionService.signalExecutionById(processInstance.getId(), "to 200");
System.out.println("当前流程是否位于200节点---->"+processInstance200.isActive("200"));//true
System.out.println("当前流程是否结束---->"+processInstance200.isEnded());//false
/*System.out.println("------------------------>使流程流向400");
ProcessInstance processInstance400=executionService.signalExecutionById(processInstance.getId(), "to 400");
System.out.println("当前流程是否位于400节点---->"+processInstance400.isActive("400"));
System.out.println("当前流程是否结束---->"+processInstance400.isEnded());*/
|
执行结果:
------------------------>使流程继续向下执行
------------------------>使流程流向200
当前流程是否位于200节点---->true
当前流程是否结束---->false
|
流向400的自己测试
由于流程定义中200和400均为state节点,所以流程在流经200或400节点后仍会停留在该节点,以下代码完成流程实例从start->200->end这一过程
ProcessInstance processInstance=executionService.startProcessInstanceByKey("demo");
//查询该流程实例的活动节点
System.out.println(processInstance.findActiveActivityNames());
//因为流程实例启动后,它会自动向下执行,直到遇到state或task等节点时暂停下来,在我们的流程定义文件中紧跟在start后的节点为state,所以流程实例会在state节点暂停下来
Execution execution=processInstance.findActiveExecutionIn("state");//查询当前流程实例的当前节点
ProcessInstance processInstance200=executionService.signalExecutionById(execution.getId(), "to 200");//此时流程流向200
System.out.println("当前流程是否位于200节点---->"+processInstance200.isActive("200"));//true
System.out.println("当前流程是否结束---->"+processInstance200.isEnded());//false
//使流程继续向下执行(结束)
System.out.println("-------使流程继续向下执行(结束)------->");
//由于200节点后没有分支仅有end这一节点,所以200与end之间transition的name属性的值可以省略,当然加上更好
ProcessInstance instance=executionService.signalExecutionById(processInstance200.getId());//流程执行到end,结束流程实例
System.out.println("当前流程是否结束---->"+instance.isEnded());//true
|
执行结果:
[state]
当前流程是否位于200节点---->true
当前流程是否结束---->false
-------使流程继续向下执行(结束)------->
当前流程是否结束---->true
|
Decision节点示例
流程图:
流程定义:
在使用Decision时,一个Decision活动应配置为以下三种中的一种
decision 会检查每一个传出的转移里的内置条件。流程的执行会采用第一个内置条件为
true 或者没有设置内置条件的转移
第一种:使用Decision内置条件(返回true或false)
即在流程定义中设置每一个transition的子节点condition,并为每一个condition填充expr属性
形如:
<condition expr="${coder=='200'}"></condition>
详细的流程定义
<?xml version="1.0" encoding="UTF-8"?>
<process name="decision" xmlns="http://jbpm.org/4.3/jpdl">
<start g="61,51,48,48" name="开始">
<transition g="-47,-17" name="to waite" to="waite"/>
</start>
<decision g="188,160,48,48" name="gowhere">
<transition g="-41,-17" name="to 200" to="200">
<condition expr="${coder=='200'}"></condition>
</transition>
<transition g="-41,-17" name="to 500" to="500">
<condition expr="${coder=='500'}"></condition>
</transition>
<transition g="-41,-17" name="to 404" to="404">
<condition expr="${coder=='404'}"></condition>
</transition>
</decision>
<state g="386,143,92,52" name="200">
<transition g="-47,-17" name="to 结束" to="结束"/>
</state>
<state g="296,261,92,52" name="500">
<transition g="-47,-17" name="to 结束" to="结束"/>
</state>
<state g="197,389,92,52" name="404">
<transition g="-47,-17" name="to 结束" to="结束"/>
</state>
<end g="498,407,48,48" name="结束"/>
<state g="114,97,92,52" name="waite">
<transition g="-65,-17" name="to gowhere" to="gowhere"/>
</state>
</process>
|
观察红色标注的部分
测试代码:
Map<String, String> map=new HashMap<String, String>();
//coder为流程定义中表达式的名称
map.put("coder", "200");
ProcessInstance processInstance=executionService.startProcessInstanceByKey("decision",map);
System.out.println("流程是否处于waite节点?"+processInstance.isActive("waite"));//true
ProcessInstance processInstanceDecision=executionService.signalExecutionById(processInstance.getId());
System.out.println("流程是否处于waite节点?"+processInstanceDecision.isActive("waite"));//false
System.out.println("流程是否处于gowhere节点?"+processInstanceDecision.isActive("gowhere"));//false
System.out.println("流程是否处于200节点?"+processInstanceDecision.isActive("200"));//true
System.out.println("流程是否处于404节点?"+processInstanceDecision.isActive("404"));//false
System.out.println("流程是否处于500节点?"+processInstanceDecision.isActive("500"));//false
|
代码说明:
在一开始定义了一个Map,在程序中手动为coder(详见流程定义中的condition的expr属性)赋值200,当流程实例启动时运行到decision时会自动计算每一个transition节点子节点condition里面的expr属性(详见流程定义中),如果某一内置条件(condition)执行为true,则就将流程执行到该节点。在使用此种方式时, condition的expr中设置的下一活动的活动名称(name),而不是transition的name属性.这里紧跟在decision活动后有三个活动200、404、500且三个活动名称依次为200、404、500,所以程序中为coder赋值200就表示将流程执行到200这个活动.
执行结果:
流程是否处于waite节点?true
流程是否处于waite节点?false
流程是否处于gowhere节点?false
流程是否处于200节点?true
流程是否处于404节点?false
流程是否处于500节点?false
|
第二种:为流程定义中decision活动设置expr属性,decision 表达式返回类型为字符串的向外转移的名字,使用此种方式不用再去为每一个transition设置condition子节点
形如:
<decision g="188,160,48,48" name="gowhere" expr="${towhere}">
这里towhere就表示流程流经decision活动后要流经的下一个transition的name属性的值
详细的流程定义文件:
<?xml version="1.0" encoding="UTF-8"?>
<process name="decision" xmlns="http://jbpm.org/4.3/jpdl">
<start g="61,51,48,48" name="开始">
<transition g="-47,-17" name="to waite" to="waite"/>
</start>
<decision g="188,160,48,48" name="gowhere" expr="${towhere}">
<transition g="-41,-17" name="to 200" to="200">
</transition>
<transition g="-41,-17" name="to 500" to="500">
</transition>
<transition g="-41,-17" name="to 404" to="404">
</transition>
</decision>
<state g="386,143,92,52" name="200">
<transition g="-47,-17" name="to 结束" to="结束"/>
</state>
<state g="296,261,92,52" name="500">
<transition g="-47,-17" name="to 结束" to="结束"/>
</state>
<state g="197,389,92,52" name="404">
<transition g="-47,-17" name="to 结束" to="结束"/>
</state>
<end g="498,407,48,48" name="结束"/>
<state g="114,97,92,52" name="waite">
<transition g="-65,-17" name="to gowhere" to="gowhere"/>
</state>
</process>
|
重点关注红色标注的地方
执行代码:
Map<String, String> map=new HashMap<String, String>();
// towhere为流程定义中表达式的名称
map.put("towhere", "to 200");
ProcessInstance processInstance=executionService.startProcessInstanceByKey("decision",map);
System.out.println("流程是否处于waite节点?"+processInstance.isActive("waite"));//true
ProcessInstance processInstanceDecision=executionService.signalExecutionById(processInstance.getId());
System.out.println("流程是否处于waite节点?"+processInstanceDecision.isActive("waite"));//false
System.out.println("流程是否处于gowhere节点?"+processInstanceDecision.isActive("gowhere"));//false
System.out.println("流程是否处于200节点?"+processInstanceDecision.isActive("200"));//true
System.out.println("流程是否处于404节点?"+processInstanceDecision.isActive("404"));//false
System.out.println("流程是否处于500节点?"+processInstanceDecision.isActive("500"));//false
|
代码解释:
从流程图中我们可以看出decision后有三个transition,且每个transition的name属性的值依次为to 200、to 404、to 500.在代码中声明了一Map对象,并为该Map添加一个以towhere作为键to 200位置的元素,然后使流程向下执行.那么当流程实例流经decision活动时,会计算decision节点expr的值,从中选择下一个transition的名称,然后向下执行.
使用此种方式为decision节点设置expr属性,设置的是下一个transition的name属性,请与第一种情况加以区别(第一种情况设置的下一活动的name)
执行结果:
流程是否处于waite节点?true
流程是否处于waite节点?false
流程是否处于gowhere节点?false
流程是否处于200节点?true
流程是否处于404节点?false
流程是否处于500节点?false
|
第三种:为decision配置一个handler的类(在流程定义中在decision节点内部配置<handler/>子节点,并设置该元素的class属性为你自己的类)该类实现了org.jbpm.api.jpdl.DecisionHandler.你需要赋写
String decide(OpenExecution execution);方法即可,在该方法最终返回decision活动后的下一个transition的name属性的值
形如:
<handler class="com.jbpm.decision.handler.HandlerDecision"></handler>
这里class="com.jbpm.decision.handler.HandlerDecision"就表示实现了org.jbpm.api.jpdl.DecisionHandler的自定义类,你只需要赋写String decide(OpenExecution execution) 方法,在该方法最终返回decision活动后的下一个transition的name属性的值
详细的流程定义文件:
<?xml version="1.0" encoding="UTF-8"?>
<process name="decision" xmlns="http://jbpm.org/4.3/jpdl">
<start g="61,51,48,48" name="开始">
<transition g="-47,-17" name="to waite" to="waite"/>
</start>
<decision g="188,160,48,48" name="gowhere">
<handler class="com.jbpm.decision.handler.HandlerDecision"></handler>
<transition g="-41,-17" name="to 200" to="200">
</transition>
<transition g="-41,-17" name="to 500" to="500">
</transition>
<transition g="-41,-17" name="to 404" to="404">
</transition>
</decision>
<state g="386,143,92,52" name="200">
<transition g="-47,-17" name="to 结束" to="结束"/>
</state>
<state g="296,261,92,52" name="500">
<transition g="-47,-17" name="to 结束" to="结束"/>
</state>
<state g="197,389,92,52" name="404">
<transition g="-47,-17" name="to 结束" to="结束"/>
</state>
<end g="498,407,48,48" name="结束"/>
<state g="114,97,92,52" name="waite">
<transition g="-65,-17" name="to gowhere" to="gowhere"/>
</state>
</process>
|
请关注红色标注部分:
测试代码:
Map<String, String> map=new HashMap<String, String>();
//towhere为流程定义中表达式的名称
map.put("towhere", "执行到200这个活动");
//map.put("towhere", "执行到404这个活动");
//map.put("towhere", "执行到500这个活动");
ProcessInstance processInstance=executionService.startProcessInstanceByKey("decision",map);
System.out.println("流程是否处于waite节点?"+processInstance.isActive("waite"));//true
ProcessInstance processInstanceDecision=executionService.signalExecutionById(processInstance.getId());
System.out.println("流程是否处于waite节点?"+processInstanceDecision.isActive("waite"));//false
System.out.println("流程是否处于gowhere节点?"+processInstanceDecision.isActive("gowhere"));//false
System.out.println("流程是否处于200节点?"+processInstanceDecision.isActive("200"));//true
System.out.println("流程是否处于404节点?"+processInstanceDecision.isActive("404"));//false
System.out.println("流程是否处于500节点?"+processInstanceDecision.isActive("500"));//false
|
处理类:
package com.jbpm.decision.handler;
import org.jbpm.api.jpdl.DecisionHandler;
import org.jbpm.api.model.OpenExecution;
@SuppressWarnings("serial")
public class HandlerDecision implements DecisionHandler {
@Override
public String decide(OpenExecution execution) {
String towhere=(String) execution.getVariable("towhere");
String result = null;
if("执行到200这个活动".equals(towhere)){
result="to 200";
}else if("执行到404这个活动".equals(towhere)){
result="to 404";
}else if("执行到500这个活动".equals(towhere)){
result="to 500";
}
return result;
}
}
|
代码解释:
在测试代码中同样创建了一个map对象,然后为该map对象添加了一个以towhere为键的值,并在流程实例向下执行的时候传递该map对象。
在HandlerDecision处理类中,通过execution.getVariable("towhere");获取towhere的value,然后依次判断,看是否与之前放进去的值匹配,若匹配的话就返回到一个你想使流程向那执行的transition的name属性的值.至此流程就会沿着这个值的方向向下执行.
执行结果:
流程是否处于waite节点?true
流程是否处于waite节点?false
流程是否处于gowhere节点?false
流程是否处于200节点?true
流程是否处于404节点?false
流程是否处于500节点?false
|
需要说明的是代码中为map对象设置的键值跟流程定义无任何关系,你可以任意设置,只要符合map的使用规律即成,完了在流程实例向下执行的时候顺带传递此map对象,最后在自定义的处理类中根据之前的设置的键来获取值,最终返回一个你期望到达的transition即可。
Task是一个任务活动,主要是在流程实例经过活动时为某一人或组指派任务(流程到达此活动时会暂停下来)
Task有一个可选的assignee属性
第一, assignee用来指示用户, 负责完成任务的人。分配人是一个任务中的字符串属性 引用一个用户。(直接指定一个字符串)
第二,这个属性默认会当做表达式来执行。(指定一个表达式,然后在代码里为该表达式赋值) 如:在这里任务被分配给#{order.owner}。这意味着首先使用order这个名字查找一个对象。 其中一个查找对象的地方是这个任务对应的流程变量。 然后getOwner()方法会用来 获得用户id, 引用的用户负责完成这个任务。
示例:
流程定义图
第一种情况:(直接指定一个字符串)
流程定义文件:
<?xml version="1.0" encoding="UTF-8"?>
<process name="task" xmlns="http://jbpm.org/4.3/jpdl">
<start g="99,112,48,48" name="start">
<transition g="-47,-17" name="to task" to="task"/>
</start>
<task g="155,221,92,52" name="task" assignee="lisi">
<transition g="-41,-17" name="to end" to="end"/>
</task>
<end g="260,350,48,48" name="end"/>
</process>
|
关注红色部分
解释,在task中直接将任务指派给lisi
测试代码(查看lisi的任务列表)
ProcessInstance processInstance=executionService.startProcessInstanceByKey("task");
System.out.println("流程是否处于task节点?"+processInstance.isActive("task"));//true
System.out.println("流程实例Id:"+processInstance.getId());
List<Task> list=taskService.findPersonalTasks("lisi");
for (Task task : list) {
System.out.println("任务活动名称:"+task.getActivityName());
System.out.println("流程实例Id:"+task.getExecutionId());
System.out.println("任务活动Id:"+task.getId());
System.out.println("任务活动创建时间:"+task.getCreateTime());
System.out.println("任务活动进度:"+task.getProgress());
System.out.println("任务活动分配给:"+task.getAssignee());
}
|
代码解释:
使用taskService.findPersonalTasks("lisi");即可取得lisi的任务列表
执行结果:
流程是否处于task节点?true
流程实例Id:task.7
任务活动名称:task
流程实例Id:task.7
任务活动Id:8
任务活动创建时间:2010-09-29 11:54:34.25
任务活动进度:null
任务活动分配给:lisi
|
第二种情况:(为task指定一表达式)
流程定义文件:
<?xml version="1.0" encoding="UTF-8"?>
<process name="task" xmlns="http://jbpm.org/4.3/jpdl">
<start g="99,112,48,48" name="start">
<transition g="-47,-17" name="to task" to="task"/>
</start>
<task g="155,221,92,52" name="task" assignee="${taskAssignee}">
<transition g="-41,-17" name="to end" to="end"/>
</task>
<end g="260,350,48,48" name="end"/>
</process>
|
关注红色部分
解释,在task中使用了表达式${taskAssignee},该值在程序执行时动态分配
测试代码(查看任务列表)
Map<String,String> map=new HashMap<String, String>();
map.put("taskAssignee", "lisi");
ProcessInstance processInstance=executionService.startProcessInstanceByKey("task",map);
System.out.println("流程是否处于task节点?"+processInstance.isActive("task"));//true
System.out.println("流程实例Id:"+processInstance.getId());
List<Task> list=taskService.findPersonalTasks("lisi");
for (Task task : list) {
System.out.println("任务活动名称:"+task.getActivityName());
System.out.println("流程实例Id:"+task.getExecutionId());
System.out.println("任务活动Id:"+task.getId());
System.out.println("任务活动创建时间:"+task.getCreateTime());
System.out.println("任务活动进度:"+task.getProgress());
System.out.println("任务活动分配给:"+task.getAssignee());
}
|
代码解释:
在程序一开始创建了一个map对象,并为该map添加一个元素,其键为流程定义中的taskAssignee,值任意分配,然后传递该map,最后查询任务列表
执行效果:
流程是否处于task节点?true
流程实例Id:task.7
任务活动名称:task
流程实例Id:task.7
任务活动Id:9
任务活动创建时间:2010-09-29 11:58:07.359
任务活动进度:null
任务活动分配给:lisi
|
最后说明一下,在jbpm中表达式$(),#()均可以成功解析