activiti中有四种网关:并行网关,排他网关,包含网关,基于事件网关
- 排它网关: 内部是一个“X”图标,用来在流程中实现决策。 当流程执行到这个网关,所有外出顺序流都会被处理一遍。 其中条件解析为true的顺序流会被选中,让流程继续运行。
- 并行网关: 内部是一个“加号”图标。它允许将流程 分成多条分支,也可以把多条分支 汇聚到一起。
- 包含网关: 内部包含一个圆圈图标,可以看做是排他网关和并行网关的结合体。 和排他网关一样,你可以在外出顺序流上定义条件,包含网关会解析它们。 但是主要的区别是包含网关可以选择多于一条顺序流,这和并行网关一样。
- 基于事件网关: 网关的每个外出顺序流都要连接到一个中间捕获事件。 当流程到达一个基于事件网关,网关会进入等待状态:会暂停执行。 与此同时,会为每个外出顺序流创建相对的事件订阅。
主要使用的是并行网关和排他网关。
(一)排他网关(也叫异或(XOR)网关,或叫基于数据的排他网关),用来在流程中实现决策。当流程执行到这个网关,所有分支都会判断条件是否为true,如果为true则执行该分支,注意,排他网关只会选择一个为true的分支执行。(即使有两个分支条件都为true,排他网关也会只选择一条分支去执行), 如果从网关出去的线所有条件都不满足则系统抛出异常。
1)图例:在部门经理审核后,走排他网关,从排他网关出来的分支有两条,一条是判断请假天数是否大于3天,另一条是判断请假天数是否小于等于3天。
2)测试:启动一个实例---->填写请假单--->部门经理审批
/** * 启动一个实例 */ @Test public void startProcessInstance() { //启动流程实例,同时还要设置流程定义的变量值 ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("myProcess_1"); System.out.println("流程实例id:" + processInstance.getProcessInstanceId()); } /** * 填请假单任务执行 */ @Test public void step1(){ Task task = taskService.createTaskQuery() .processDefinitionKey("myProcess_1") .taskAssignee("张三") .singleResult(); if(task!=null){ Holiday holiday = new Holiday(); holiday.setDays(5F); //请假5天 Map<String,Object> map = new HashMap<>(); map.put("holiday",holiday);//流程变量赋值 taskService.complete(task.getId(),map); System.out.println("用户任务执行完毕..."); } } /** * 部门经理完成审批 */ @Test public void step2() { Task task = taskService.createTaskQuery().processDefinitionKey("myProcess_1") .taskAssignee("李四").singleResult(); if (task != null) { taskService.complete(task.getId());//完成任务时,设置流程变量的值 System.out.println("用户任务执行完毕..."); } }
查看数据库,可以看到张三请假5天,部门经理审批后经过网关流转到总经理审批。
后续执行总经理审批和人事审批,最后数据库如下:
(二)并行网关
并行网关允许将流程分成多条分支,也可以把多条分支汇聚到一起,并行网关的功能是基于进入和外出顺序流的:
- fork分支:并行后的所有外出顺序流,为每个顺序流都创建一个并发分支。
- join汇聚:所有到达并行网关,在此等待的进入分支,直到所有进入顺序流的分支都到达以后,流程就会通过汇聚网关。
如果同一个并行网关有多个进入和多个外出顺序流,它就同时具有分支和汇聚功能。这时,网关会先汇聚所有进入的顺序流,然后再切分成多个并行分支。与其他网关的主要区别是,并行网关不会解析条件。即使顺序流中定义了条件,也会被忽略。
人事执行审批,流转到网关,启动2条并行任务
/** * 人事审批 */ @Test public void step4() { Task task = taskService.createTaskQuery().processDefinitionKey("myProcess_2") .taskAssignee("赵六").singleResult(); if (task != null) { taskService.complete(task.getId());//完成任务时,设置流程变量的值 System.out.println("用户任务执行完毕..."); } }
见数据库记录,历史节点表
运行时任务节点表
运行时流程执行实例表
财务结算和行政考勤是两个execution分支,在ACT_RU_EXECUTION表有两条记录分别是财务结算和行政考勤,ACT_RU_EXECUTION还有一条记录表示该流程实例。待行政考勤和财务结算任务全部完成,在汇聚点汇聚,通过parallelGateway并行网关。并行网关在业务应用中常用于会签任务,会签任务即多个参与者共同办理的任务。
后续继续执行行政考勤和财务会计流程
/** * 行政考勤 */ @Test public void step5() { Task task = taskService.createTaskQuery().processDefinitionKey("myProcess_2") .taskAssignee("王五").singleResult(); if (task != null) { taskService.complete(task.getId());//完成任务时,设置流程变量的值 System.out.println("用户任务执行完毕..."); } } /** * 财务会计 */ @Test public void step6() { Task task = taskService.createTaskQuery().processDefinitionKey("myProcess_2") .taskAssignee("孙八").singleResult(); if (task != null) { taskService.complete(task.getId());//完成任务时,设置流程变量的值 System.out.println("用户任务执行完毕..."); } }
有并行网关的汇聚结点:说明有一个分支已经到汇聚,等待其它的分支到达。
当所有分支任务都完成,都到达汇聚结点后,所有分支到达汇聚结点,并行网关执行完成。此时查看ACT_RU_EXECUTION表和ACT_RU_TASK表中的可执行实例和可执行任务都不复存在,表明该流程已经结束。