温馨提示:您的每一次转载,体现了我写此文的意义!!!烦请您在转载时注明出处http://www.blogjava.net/sxyx2008/谢谢合作!!!

雪山飞鹄

温馨提示:您的每一次转载,体现了我写此文的意义!!!烦请您在转载时注明出处http://www.blogjava.net/sxyx2008/谢谢合作!!!

BlogJava 首页 新随笔 联系 聚合 管理
  215 Posts :: 1 Stories :: 674 Comments :: 0 Trackbacks

本文电子版文档下载
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中表达式$(),#()均可以成功解析

posted on 2010-09-29 13:52 雪山飞鹄 阅读(3888) 评论(0)  编辑  收藏 所属分类: jbpm4

只有注册用户登录后才能发表评论。


网站导航: