Activiti流程定义语言

1、流程(process)

  bpmn文件一个流程的根元素。一个流程就代表一个工作流。

2、顺序流(sequenceFlow)

  顺序流是连接两个流程节点的连线,代表一个节点的出口。流程执行完一个节点后,会沿着节点的所有外出顺序流继续执行。 就是说,BPMN 2.0默认的行为就是并发的: 两个外出顺序流会创造两个单独的,并发流程分支。

  顺序流主要由4个属性组成:

    Id: 唯一标示,用来区分不同的顺序流

    sourceRef:连线的源头节点ID

    targetRef:连线的目标节点ID

    name(可选):连线的名称,不涉及业务,主要用于显示

      说明:

      1)     结束节点没有出口

      2)     其他节点有一个或多个出口。如果有一个出口,则代表是一个单线流程;如果有多个出口,则代表是开启并发流程。

3、节点

  1、开始事件节点(startEvent)

    开始事件用来指明流程在哪里开始。开始事件的类型(流程在接收事件时启动, 还是在指定时间启动,等等),定义了流程如何启动, 这通过事件中不同的小图表来展示。 在XML中,这些类型是通过声明不同的子元素来区分的。

    1)空开始事件

      空开始事件技术上意味着没有指定启动流程实例的触发条件。最常用的一种开始,意味着流程的启动需要手动触发,通过调用api的startProcessInstanceByXXX方法。注意: 子流程都有一个空开始事件。

      ProcessInstanceprocessInstance =runtimeService.startProcessInstanceByXXX();

      图形标记:空开始事件显示成一个圆圈,没有内部图表(没有触发类型)

      XML结构如下:<startEventid="start"name="my start event"/>

    2)定时开始事件

      定时开始事件用来在指定的时间创建流程实例。 它可以同时用于只启动一次的流程 和应该在特定时间间隔启动多次的流程。

      注意:

        1.子流程不能使用定时开始事件。

        2.定时开始事件在流程发布后就会开始计算时间。 不需要调用     startProcessInstanceByXXX,虽然也而已调用启动流程的方法, 但是   那会导致调用            startProcessInstanceByXXX时启动过多的流程。

        3.当包含定时开始事件的新版本流程部署时, 对应的上一个定时器就会    被删除。这是因为通常不希望自动启动旧版本流程的流程实例。

      图形标记:定时开始事件显示为一个圆圈,内部是一个表。

      XML内容:

        定时开始事件的XML内容是普通开始事件的声明,包含一个定时定义子元素。

        示例:流程会启动4次,每次间隔5分钟,从2013年9月18日,12:10开始计时。

 <startEvent id="theStart">
<timerEventDefinition>
<timeCycle>R4/2013-09-18T12:13/PT5M</timeCycle>
</timerEventDefinition>
</startEvent>

        示例:流程会根据选中的时间启动一次。

 <startEventid="theStart">
<timerEventDefinition>
<timeDate>2013-10-31T23:59:24</timeDate>
</timerEventDefinition>
</startEvent>

  2、结束事件节点(endEvent)

    结束事件表示(子)流程(分支)的结束。 结束事件都是触发事件。 这是说当流程达到结束事件,会触发一个结果。 结果的类型是通过事件的内部黑色图标表示的。

    1)空结束事件

      空结束事件意味着到达事件时不会指定抛出的结果。 这样,引擎会直接结束当前执行的分支,不会做其他事情。

      图形标记:空结束事件是一个粗边圆圈,内部没有小图表(无结果类型)

      XML内容:<endEvent id="end" name="my end event"/>

      空结束事件的XML内容是普通结束事件定义,不包含子元素 (其他结束事件类型都会包含声明类型的子元素)。

  3、任务节点 (Task)

    1)接收任务节点(receiveTask)

      接收任务是一个简单任务,它会等待对应消息的到达。 当前,官方只实现了这个任务的java语义。 当流程达到接收任务,流程状态会保存到数据库中。

      在任务创建后,意味着流程会进入等待状态, 直到引擎接收了一个特定的消息, 这会触发流程穿过接收任务继续执行。

      图形标记:接收任务显示为一个任务(圆角矩形),右上角有一个消息小标记。 消息是白色的(黑色图标表示发送语义)

      XML内容:<receiveTask id="waitState" name="wait"/>

      当前任务(一般指机器自动完成,但需要耗费一定时间的工作)完成后,向后推移流程,可以调用runtimeService.signal(executionId),传递接收任务上流程的id。

      演示代码如下:

ProcessInstance pi =runtimeService.startProcessInstanceByKey("receiveTask");
Execution execution=runtimeService.createExecutionQuery()
.processInstanceId(pi.getId())
                     .activityId("waitState")
                     .singleResult();
assertNotNull(execution);
runtimeService.signal(execution.getId());

    2)用户任务节点 (userTask)

      用户任务用来设置必须由人员完成的工作。 当流程执行到用户任务,会创建一个新任务, 并把这个新任务加入到分配人或群组的任务列表中。

       图形标记:用户任务显示成一个普通任务(圆角矩形),左上角有一个小用户图标。

      XML内容XML中的用户任务定义如下。id属性是必须的。 name属性是可选的。

      <userTask id="theTask" name="Important task"/>

      用户任务也可以设置描述(实际上所有BPMN 2.0元素都可以设置描述)。 添加documentation元素可以定义描述。

<userTask id="theTask" name="Schedule meeting">
<documentation>
Schedule an engineering meeting for next week with the new hire.
</documentation>

      在实际应用中,用户接到任务后可以参照任务描述来办理任务,描述文本可以通过标准的java方法来获得:task.getDescription()

      任务分配

      用户任务的办理都需要人工的参与。用户任务可以分为两大类。私有任务和公有任务(可接任务)。

        私有任务

        私有任务即有直接分配给指定用户的任务。只有一个用户可以成为任务     的执行者。 在activiti中,用户叫做执行者。 拥有执行者的用户任务  (即私有任务)对其他用户是不可见的。只能出现执行者的个人任务列表中.

        直接把用户任务分配给指定用户使用assignee属性,XML代码如下:

        <userTask id="theTask" name="my task" activiti:assignee="sirius"/>

        Assignee属性对应的值为一个用户的ID。

        直接分配给用户的任务可以通过TaskService像下面这样办理:

List<Task>tasks =taskService.createTaskQuery().taskAssignee("sirius").list();

Task task = tasks.get(0);// 假设任务集合的第一条是要办理的任务

taskService.complete(task.getId());

        公有任务

          有的用户任务在指派时无法确定具体的办理者,这时任务也可以加入到     人员的候选任务列表中,然后让这些人员选择性认领和办理任务。

          公有任务的分配可以分为指定候选用户和候选组两种。

            a) 把任务添加到一批用户的候选任务列表中,使用candidateUsers     属   性,XML内容如下:

              <userTaskid="theTask"name="my task"activiti:candidateUsers="sirius,kermit"/>

              candidateUsers属性内为用户的ID,多个用户ID之间使用(半角)逗 号间隔。

            b)  把任务添加到一个或多个候选组下,这时任务对组下的所有用户可      见,首先得保证每个组下面有用户,通过IdentityService对象创建用户   和组,然后把用户添加到对应的组下。

         然后配置组任务,使用candidateGroups属性,XML内容如下:

          <userTask  id="theTask"   name="my task"     activiti:candidateGroups="testGroup,developGroup"/>

          间接分配给用户的任务,可以通过TaskService像下面这样操作:

List<Task>tasks =taskService.createTaskQuery()

                                  .taskCandidateUser("sirius").list();

Task task = tasks.get(0);// 假设任务集合的第一条是要办理的任务

String taskId = task.getId();

taskService.claim(taskId ,“sirius”); //认领任务,让用户成为任务的执行者

taskService.complete(taskId );

            说明:

              1.要维护用户和组得使用用户管理服务对象,使用       processEngine  得到IdentityService。

              2.要分配组任务必须先创建组,而且组下得有用户,用户和组的     最关键属性是ID。

              3.使用newUser(userId)和newGroup(groupId)创建用户  和组。

              4.使用createMembership(userId,groupId)把用户挂到  组下。

              5.办理候选任务,首先得认领任务,让用户成为任务的执行者。

            如果上面的方式还不够灵活,那么我们也可以自定义一个任务分配处理器,通过代码的方式来动态设置任务的属性。XML代码如下:

<userTask id="task1" name="My task">
<extensionElements>
<activiti:taskListener event="create" class="org.activiti.MyAssignmentHandler"/>
</extensionElements>
</userTask>

            DelegateTask会传递给TaskListener的实现, 通过它可以设置执行人,候选人和候选组:

Public class MyAssignmentHandler implements TaskListener {

    Public void notify(DelegateTask delegateTask){
// 执行用户搜索相关代码
...
// 然后把获取到的用户通过下面方法,设置给当前触发事件的任务
delegateTask.setAssignee("sirius");
//delegateTask.addCandidateUser("kermit");
//delegateTask.addCandidateGroup("testGroup");
...
}
}

       上述两个虽然都可以统称为任务节点,但是还是有本质区别:

          1.receiveTask主要代表机器自动执行的,userTask代表人工干预的。

          2.receiveTask任务产生后会在act_ru_execution表中新增一条记录,  而userTask产生后会在act_ru_execution和act_ru_task(主要记录任   务的发布时间,办理人等信息)中各产生一条记录。

          3.receiveTask任务提交方式使用RuntimeService的signal方法提交,  userTask任务提交方式使用TaskService的complete方法提交。

    

上一篇:实例演示使用RDIFramework.NET 框架的工作流组件进行业务流程的定义—请假申请流程-Web


下一篇:如何修改配置以修复ThinkPad 小红帽滚轮失效?