1. 排他网关 ExclusiveGateway
(1)概念
排他网关,用来在流程中实现决策。 当流程执行到这个网关,所有分支都会判断条件是否为true,如果 为true则执行该分支,排他网关只会选择一个为true的分支执行,如果有两个分支条件都为true,排他网关会选择id值较小的一条分支去执行
当从网关出去的线所有条件都不满足时则会抛出异常
org.activiti.engine.ActivitiException: No outgoing sequence flow of the exclusive gateway 'exclusivegateway' could be selected for continuing the process at
org.activiti.engine.impl.bpmn.behavior.ExclusiveGatewayActivityBehavior.leave(ExclusiveGatewayActivityBehavior.java:85)
(2)测试
public class ExclusiveTest {
@Test
public void deploy() {
//1.获取ProcessEngine对象
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
//2.获取RepositoryService
RepositoryService service = engine.getRepositoryService();
//3.部署
Deployment deploy = service.createDeployment()
.addClasspathResource("bpmn/evection-exclusive.bpmn")
.addClasspathResource("bpmn/evection-exclusive.png")
.name("出差申请流程-排他网关")
.deploy();
System.out.println("id: " + deploy.getId());
System.out.println("name: " + deploy.getName());
//service.deleteDeployment("57501", true);
}
@Test
public void startProcess() {
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = engine.getRuntimeService();
Evection evection = new Evection();
evection.setNum(4d);
Map<String, Object> map = new HashMap<>();
map.put("evection", evection);
ProcessInstance instance = runtimeService.startProcessInstanceByKey("evection-exclusive", map);
System.out.println("流程定义id:" + instance.getProcessDefinitionId());
}
@Test
public void completeTask() {
String userId = "lisi";
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = engine.getTaskService();
Task task = taskService.createTaskQuery().processDefinitionKey("evection-exclusive").taskAssignee(userId).singleResult();
if (task != null) {
Evection evection = new Evection();
evection.setNum(2d);
Map<String, Object> map = new HashMap<>();
map.put("evection", evection);
taskService.complete(task.getId(), map);
System.out.println("任务:" + task.getId() + "完成");
}
}
}
2. 并行网关ParallelGateway
(1)概念
并行网关允许将流程分成多条分支,也可以把多条分支汇聚到一起,并行网关的功能是基于进入和外出顺序流的:
- fork分支: 并行后的所有外出顺序流,为每个顺序流都创建一个并发分支
- join汇聚: 所有到达并行网关,在此等待的进入分支,直到所有进入顺序流的分支都到达以后,流程就会通过汇聚网关
注意,如果同一个并行网关有多个进入和多个外出顺序流,它就同时具有分支和汇聚功能,这时,网关会先汇聚所有进入的顺序流,然后再切分成多个并行分支,并行网关与其他网关的主要区别是,并行网关不会解析条件,即使顺序流中定义了条件,在流程流转时也会被忽略
(2)测试
public class 8ParallelTest {
@Test
public void deploy() {
//1.获取ProcessEngine对象
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
//2.获取RepositoryService
RepositoryService service = engine.getRepositoryService();
//3.部署
Deployment deploy = service.createDeployment()
.addClasspathResource("bpmn/evection-parallel.bpmn")
//.addClasspathResource("bpmn/evection-exclusive.png")
.name("出差申请流程-并行网关")
.deploy();
System.out.println("id: " + deploy.getId());
System.out.println("name: " + deploy.getName());
//service.deleteDeployment("57501", true);
}
@Test
public void startProcess() {
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = engine.getRuntimeService();
Evection evection = new Evection();
evection.setNum(4d);
Map<String, Object> map = new HashMap<>();
map.put("evection", evection);
ProcessInstance instance = runtimeService.startProcessInstanceByKey("evection-parallel", map);
System.out.println("流程定义id:" + instance.getProcessDefinitionId());
}
@Test
public void completeTask() {
String userId = "lisi";
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = engine.getTaskService();
Task task = taskService.createTaskQuery().processDefinitionKey("evection-parallel").taskAssignee(userId).singleResult();
if (task != null) {
taskService.complete(task.getId());
System.out.println("任务:" + task.getId() + "完成");
}
}
}
流程流转至网关处,可查看 act_ru_task
表对应的数据,有两个正在执行的任务
查看 act_ru_execution
表,有多个分支正在运行
并行任务执行不分先后,由任务的负责人去执行即可,处理完一个任务则 act_ru_task
减少一条记录(负责人为技术经理对应的任务)
有并行网关的汇聚结点,则说明有一个分支已经到汇聚,等待其它的分支到达
当所有分支任务都完成,都到达汇聚结点后,查看 act_ru_task
表,执行流程实例已经变为总经理审批(出差天数大于等于
3),说明流程执行已经通过并行网关(即所有分支到达汇聚结点,并行网关执行完成)
3. 包含网关InclusiveGateway
(1)概念
包含网关可以看做是排他网关和并行网关的结合体,和排他网关一样,你可以在外出顺序流上定义条件,包含网关会解析它们,但其主要的区别是包含网关可以选择多于的一条顺序流,这和并行网关一样,包含网关的功能是基于进入和外出顺序流的:
- 分支: 所有外出顺序流的条件都会被解析,结果为true的顺序流会以并行方式继续执行,会为每个顺序流创建 一个分支
- 汇聚: 所有并行分支到达包含网关会进入等待状态,直到每个进入顺序流的分支都到达,这是与并行网关最大的不同(包含网关只会等待被选中且执行了的进入顺序流,在汇聚之后, 流程会穿过包含网关继续执行)
(2)测试
public class InclusiveTest {
@Test
public void deploy() {
//1.获取ProcessEngine对象
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
//2.获取RepositoryService
RepositoryService service = engine.getRepositoryService();
//3.部署
Deployment deploy = service.createDeployment()
.addClasspathResource("bpmn/evection-inclusive.bpmn")
//.addClasspathResource("bpmn/evection-inclusive.png")
.name("出差申请流程-包含网关")
.deploy();
System.out.println("id: " + deploy.getId());
System.out.println("name: " + deploy.getName());
}
@Test
public void startProcess() {
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = engine.getRuntimeService();
Evection evection = new Evection();
evection.setNum(4d);
Map<String, Object> map = new HashMap<>();
map.put("evection", evection);
ProcessInstance instance = runtimeService.startProcessInstanceByKey("evection-inclusive", map);
System.out.println("流程定义id:" + instance.getProcessDefinitionId());
}
@Test
public void completeTask() {
String userId = "zhangsan";
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = engine.getTaskService();
Task task = taskService.createTaskQuery().processDefinitionKey("evection-inclusive").taskAssignee(userId).singleResult();
if (task != null) {
taskService.complete(task.getId());
System.out.println("任务:" + task.getId() + "完成");
}
}
}
执行流程
a. 当流程执行到第一个包含网关后,会根据条件判断,当前要走哪几个分支
act_ru_task
表信息
技术经理审批、人事经理审批都是当前并行执行的任务
act_ru_execution
表信息
第一条记录代表包含网关分支,第二、三条记录代表要执行的分支
如果有一个分支执行先走到汇聚结点的分支,要在此等待其它执行分支
b. 先执行技术经理审批,然后查看当前任务表 act_ru_task
,还剩人事经理的任务
查看 act_ru_execution
表信息
人事经理的分支还在,技术经理的分支已走到汇聚节点
c. 人事经理进行任务处理,然后查看当前任务表 act_ru_task
,任务来到了总经理这边
查看 act_ru_execution
表信息
包含网关执行完成,分支和汇聚就从 act_ru_execution
删除
注:
- 如果包含网关中设置的条件在流程变量中不存在,则会抛出异常
- 分支需要判断条件,只有符合条件的分支才会执行,符合条件的分支最终才进行汇聚
4. 事件网关EventGateway
事件网关允许根据事件判断流向,网关的每个外出顺序流都要连接到一个中间捕获事件,当流程到达一个基于事件网关时,网关会进入等待状态(即暂停执行),与此同时,会为每个外出顺序流创建相对应的事件订阅,事件网关的外出顺序流和普通顺序流不同,这些顺序流不会真的"执行",相反它们让流程引擎去决定执行到事件网关的流程需要订阅哪些事件,同时还要考虑以下条件:
- 事件网关必须有两条或以上外出顺序流
- 事件网关后,只能使用
intermediateCatchEvent
类型(activiti不支持基于事件网关后连接ReceiveTask
) - 连接到事件网关的中间捕获事件必须只有一个入口顺序流
intermediateCatchEvent 类型:
- Message Event 消息事件
- Singal Event 信号事件
- Timer Event 定时事件
评论 (0)