您的位置:首页 > 产品设计 > 产品经理

(转)JBPM案例详解五

2011-07-01 10:19 274 查看
一、该版本中使用了Pooled Actor机制,而不是actor-id。

**解释:就是说通过Pooled Actor可以将一个任务一次分配给一组(多个)参与者,
注意这和之前不一样,之前是针对同一个任务,然后产生多个任务实例对象,
然后每个实例对象对应一个任务的参与者,其实还是相当于一个任务对应了一个参与者;
现在说的使用Pooled Actor是将一个任务的一个任务实例对象分配给一组参与者。

**运行原理:
当把一个任务的一个任务实例对象分配给一组参与者之后,
那么该组参与者的每个成员登陆系统后,都可以看到该任务列表
(此时调用显示用户代办列表的方法较之前有区别,是带有pooled字符串的方法),
但是当其中的一个参与者开启了任务(调用了start()方法,不论之后是否也调用了end()处理任务的方法),
那么此时该组的其他参与者就不能再看到该任务了,因为任务已经得到了处理;
换句话说就是任务只有一个,而处理任务的参与者却有多个,
但是最终任务的处理只能被一个参与者处理,任务处理完之后就可以进入下一个节点了。

****具体解释:
其实当JBPM流转到包含有分配一组参与者的任务<task>的节点<task-node>的时候,
和之前一样,仍然会自动创建任务实例对象,此处因为使用的是PooledActor为任务分配的参与者,
所以JBPM对任务实例对象做了特殊处理,我们会在数据库表中看到,虽然创建了任务实例,
但是对象的表记录中的actorId是null,根本就没有值,这里的原因就是因为是一个任务分给了一组,
但是最后必须有一个参与者处理,该actorId字段的值,是在该任务实例对象调用start()开始方法的时候,
通过代码指定一个要处理该任务的参与者编号(当然这个参与者必须属于组之中的一个),
这样该任务就只对调用start()方法时指定了参与者的这个参与者可见,不管该参与者是不是进行处理该任务,
即是否调用end()方法,只要它在启动任务,即调用start()方法时指定了自己作为任务的处理者,
那么对于组中的其他参与者就对该任务都不可见了。

**具体实现:三个大步骤!!!

1.在流程定义文件中为任务指定一个类
<task-node name="taskNodeName">
<task name="taskName">
<assignment class="com.lj.handler.PooledAssignmentHandler"/>
</task>
<transition name="transitionName" to="flowToName"></transition>
</task-node>

2.分配参与者的类的具体实现:
public class PooledAssignmentHandler implements AssignmentHandler{
public void assign(Assignable assignable, ExecutionContext executionContext) throws Exception{
//一组参与者的编号ID
String[] actors = {"1","2","3"};
//为任务分配一组参与者
assignable.setPooledActors(actors);
}
}

3.获取登陆人员代办任务列表的时候和之前有点区别:
//根据当前登陆的用户ID获得任务列表
//估计这样只能获取通过setPooledActors()方法分配的任务,之前那种估计还得用之前的方式,自己试验后确实是这样
//所以下边获得的都是通过setPooledActors()这种方法分配的参与者的任务列表
List list = jbpmContext.getTaskMgmtSession().findPooledTaskInstances(userId);
//循环各任务
for(int i = 0; i < list.size(); i++){
//得到一个任务
TaskInstance taskInstance = (TaskInstance)list.get(i);
/*启动任务,因为上面说过创建任务的时候actor-id字段是没有参与者的值的,
所以启动流程的时候要把启动流程的参与者(即自己)设置为处理该任务的参与者,
也就是说这样的话actor-id字段中的值就是userId了,
那么此时不论userId参与者是否调用end()方法来处理该任务,
那么改组的其他参与者都将不能再看到该任务了*/
taskInstance.start(userId);
}

**提示:获得任务列表后对于这种使用PooledActor的方式的处理,
一般不立即就start()任务,因为如果立即启动的话那么意味着谁先登陆谁先看到这个任务那么这个任务就由谁办理;
所以一般都是先显示,当点击"办理"等一个动作后,然后再调用start()方法,并且传入当前参与者的ID,
表示当前用户要对任务进行处理。

一、该版本引入<decision>节点的使用:又称决策节点或路由节点

作用:就是流程到达该节点之后,可以通过自己的需求,可以通过一定的运算法则动态的选择接下来要流转到那个节点

使用方法:有两种使用方式

1.可以在<decision>节点的<transition>元素中通过<condition>元素指定一定的条件,
如果条件满足,那么就流向包含该<condition>元素的<transition>元素指向的节点
如果条件不满足,则不流向包含该<condition>元素的<transition>元素指向的节点
这里可能会有在一个节点中出现多个<transition>的情况,此时选择第一个满足条件的<transition>转向作为流程的转向

<decision name="nodeName">
<transition name="transitionName" to="flowToName">
<!--注意小于号<不能直接写,因为这是在xml文件中,要遵从xml的约束-->
<condition>#{days lt 5}</condition>
</transition>

<transition name="transitionName" to="flowToName">
<!--注意大于号>不能直接写,因为这是在xml文件中,要遵从xml的约束-->
<condition>#{days gt 5}</condition>
</transition>
</decision>

**说明:#{days lt 5}中的days是变量名,所以当流程流转到该处之前要为该变量赋值,
赋值方式和之前在<assignment>中为actor-id指定的变量赋值一样。

**注意:如果要用上边这种方式,有的时候会因为<condition>中的表达式不正确而出现问题,所以不推荐,推荐使用下边这种方法!!!

2.可以通过<decision>节点的<handler>来指定一个实现DecisionHandler接口的类,
实现类的指定方法会返回一个字符串,这个字符串就是该<decision>节点中的<transition>元素的name属性的值,
即<transition>的名称,也就是返回的字符串与哪个<transition>名称对应那么就转向那个<transition>指定的节点

<decision name="nodeName">
<!--指定处理分流的类全名-->
<handler class="className"></handler>

<transition name="transitionName" to="flowToName">
</transition>

<transition name="transitionName" to="flowToName">
</transition>
</decision>

//实现类
public class Decision implements DecisionHandler{
public String decide(ExecutionContext executionContext) throws Exception {
int days = executionContext.getContextInstance().getVariable("days").intValue();
if(days > 1000){
return "transitionName";
}else{
return "transitionName";
}
}
}

注意:上边的处理类中获取了一个流程变量,所以流程流转到<decision>节点之前还是要将流程变量先进行赋值!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: