概述
文章目录
- 排他网关
- 案例:
- 并行网关
- 案例:
- 包容网关
- 案例:
- 事件网关
- 1. 定时事件
- 1.1 定时器启动事件
- 案例
网关(gateway)用来控制流程的流向。来实现复杂的审批流程。
网关的分类包括:排他网关、并行网关、包容网关、事件网关。
排他网关
exclusive gateway也成为异域网关XORgateway。用于对流程中的决策建模。当执行到这个网关的时候,会按照所有出口顺序定义的顺序对他们进行计算。选择第一个条件计算为true的顺序流(当没有设置条件的时候,默认顺序六为true)继续流程。
注意:这里出口顺序流的含义与BPMN2.0中的一般情况不同。一般的,会选择所有计算条件为true的顺序流,并行执行。而使用排他网关时,只选择一条顺序流。当多条顺序流条件都为true的时候,仅会选择在XML中最先定义的顺序流继续执行。若没有可选的顺序流则会抛出异常。
案例:
绘制排他网关流程图,并分配处理人
部署流程、运行实例、与完成任务
package com.hx;
import org.flowable.engine.*;
import org.flowable.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.idm.api.Group;
import org.flowable.idm.api.User;
import org.flowable.task.api.Task;
import org.junit.Before;
import org.junit.Test;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author Huathy
* @date 2022-05-12 23:40
* @description 排他网关
*/
public class Test9_ExclusiveGateway {
ProcessEngineConfiguration configuration = null;
ProcessEngine processEngine = null;
static String PROC_DEF_ID = "qjlc-exclusive:1:4";
@Before
public void before() {
// 通过 ProcessEngineConfiguration 构建我们需要的 ProcessEngine
configuration = new StandaloneInMemProcessEngineConfiguration();
// 配置相关数据库连接
configuration.setJdbcDriver("com.mysql.cj.jdbc.Driver");
configuration.setJdbcUsername("root");
configuration.setJdbcPassword("admin");
configuration.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/flowable1?serverTimeZone=UTC&nullCatalogMeansCurrent=true");
// 如果数据库中的表结构不存在则新建
configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
processEngine = configuration.buildProcessEngine();
}
/**
* 部署一个流程
*/
@Test
public void test_deploy() {
// 2. 获取 RepositoryService
RepositoryService repositoryService = processEngine.getRepositoryService();
// 3. 完成流程部署操作
Deployment deploy = repositoryService.createDeployment()
// 关联要部署的流程文件
.addClasspathResource("请假流程-排他网关.bpmn20.xml")
.name("请假流程-排他网关-2023")
.deploy(); // 部署流程
System.out.println("deploy.getId() => " + deploy.getId());
System.out.println("deploy.getName() => " + deploy.getName());
}
/**
* 运行流程实例
*/
@Test
public void test_run_proc() {
RuntimeService runtimeService = processEngine.getRuntimeService();
// 给流程定义中的UEL表达式赋值
Map<String, Object> params = new HashMap<>();
params.put("num", 2);
// params.put("num", 3);
// params.put("num", 4);
ProcessInstance processInstance = runtimeService.startProcessInstanceById(PROC_DEF_ID, params);
System.out.println("processInstance.getId() = " + processInstance.getId());
}
/**
* 任务完成
*/
@Test
public void complete_task() {
TaskService taskService = processEngine.getTaskService();
Task task = taskService.createTaskQuery()
.processDefinitionId(PROC_DEF_ID)
.taskCandidateOrAssigned("xixi")
.singleResult();
if (task != null) {
taskService.complete(task.getId());
System.out.println("任务完成");
}
}
}
若从网关出去的线,所有条件都不满足的情况下,会抛出如下异常。
但是注意的是这里的任务并没有结束,还是原来的任务,我们可以重新设置流程变量:
@Test
public void test_set_variables(){
TaskService taskService = processEngine.getTaskService();
Task task = taskService.createTaskQuery().processDefinitionId(PROC_DEF_ID)
.taskCandidateOrAssigned("xixi").singleResult();
taskService.setVariable(task.getId(),"num",10);
}
这里与之前案例中讲到的分支情况要做一个对比,其不同点在于使用网关的情况下,任务失败出现异常,该流程并未结束。而分支的情况若出现异常,则流程异常结束。这也是为什么需要排他网关的原因。
并行网关
并行网关允许将流程拆分为多个分支,也可以将多个分支汇集到一起。并行网关的功能是基于流入流出的顺序流。
- fork分支:用于任务的开始。并行后所有外出的顺序流,为每个顺序流都创建一个并发分支。
- join汇聚:用于任务的汇聚。所有道道并行网关,在此处等待的进入分支,直到所有进入顺序流的分支都达到后,流程会通过汇集网关。
注意:如果同一个并行网关有多个进入和外出顺序流,他就同时具有分支和汇聚的功能。此时网关会线汇聚所有进入的顺序流,然后再切分为多个并行分支。
区别:并行网关并不会解析条件。即使顺序流中定义了条件,也会被忽略。
案例:
绘制流程图,并分配处理人。
当流程流转到并行网关位置的时候,在ACT_RU_TASK表和ACT_RU_EXECUTION表会新增俩条记录。一个流程可以包含多个任务和执行实例。
我们先运行完成任务的方法,完成一个经理审批,可以看到任务没有继续向下流转,而是等到所有并行任务完成后再向下流转。
package com.hx;
import org.flowable.engine.*;
import org.flowable.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.junit.Before;
import org.junit.Test;
import java.util.HashMap;
import java.util.Map;
/**
* @author Huathy
* @date 2022-05-12 23:40
* @description 并行网关
*/
public class Test10_ParallelGateway {
ProcessEngineConfiguration configuration = null;
ProcessEngine processEngine = null;
static String PROC_DEF_ID = "qjlc-parallel:1:20004";
@Before
public void before() {
// 通过 ProcessEngineConfiguration 构建我们需要的 ProcessEngine
configuration = new StandaloneInMemProcessEngineConfiguration();
// 配置相关数据库连接
configuration.setJdbcDriver("com.mysql.cj.jdbc.Driver");
configuration.setJdbcUsername("root");
configuration.setJdbcPassword("admin");
configuration.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/flowable1?serverTimeZone=UTC&nullCatalogMeansCurrent=true");
// 如果数据库中的表结构不存在则新建
configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
processEngine = configuration.buildProcessEngine();
}
/**
* 部署一个流程
*/
@Test
public void test_deploy() {
// 2. 获取 RepositoryService
RepositoryService repositoryService = processEngine.getRepositoryService();
// 3. 完成流程部署操作
Deployment deploy = repositoryService.createDeployment()
// 关联要部署的流程文件
.addClasspathResource("请假流程-并行网关.bpmn20.xml")
.name("请假流程-并行网关-2023")
.deploy(); // 部署流程
System.out.println("deploy.getId() => " + deploy.getId());
System.out.println("deploy.getName() => " + deploy.getName());
}
/**
* 运行流程实例
*/
@Test
public void test_run_proc() {
RuntimeService runtimeService = processEngine.getRuntimeService();
ProcessInstance processInstance = runtimeService.startProcessInstanceById(PROC_DEF_ID);
System.out.println("processInstance.getId() = " + processInstance.getId());
}
/**
* 任务完成
*/
@Test
public void complete_task() {
TaskService taskService = processEngine.getTaskService();
Task task = taskService.createTaskQuery().processDefinitionId(PROC_DEF_ID)
.taskCandidateOrAssigned("whx").singleResult();
if (task != null) {
taskService.complete(task.getId());
System.out.println("任务完成");
}
}
}
包容网关
包容网关可以看作是排他网关与并行网关的结合。并行网关也会像排他网关一样,解析定义条件。但区别是包含网关可以选择多条顺序流,这与并行网关是一样的。
- 分支:所有外出顺序流的条件都会被解析,结果为true的顺序流会以并行的方式继续执行,会为每个顺序流创建一个分支。
- 汇聚:所有并行分支达到包含网关,会进入等待状态,直到每个包含流程token的进入顺序流的分支都到达。即包含网关只等待被选中执行了的进入顺序流。这也是与并行网关的区别。
案例:
package com.hx;
import org.flowable.engine.*;
import org.flowable.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.junit.Before;
import org.junit.Test;
import java.util.HashMap;
import java.util.Map;
/**
* @author Huathy
* @date 2022-05-12 23:40
* @description 包容网关
*/
public class Test11_InclusiveGateway {
ProcessEngineConfiguration configuration = null;
ProcessEngine processEngine = null;
@Before
public void before() {
// 通过 ProcessEngineConfiguration 构建我们需要的 ProcessEngine
configuration = new StandaloneInMemProcessEngineConfiguration();
// 配置相关数据库连接
configuration.setJdbcDriver("com.mysql.cj.jdbc.Driver");
configuration.setJdbcUsername("root");
configuration.setJdbcPassword("admin");
configuration.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/flowable1?serverTimeZone=UTC&nullCatalogMeansCurrent=true");
// 如果数据库中的表结构不存在则新建
configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
processEngine = configuration.buildProcessEngine();
}
/**
* 部署一个流程
*/
@Test
public void test_deploy() {
// 2. 获取 RepositoryService
RepositoryService repositoryService = processEngine.getRepositoryService();
// 3. 完成流程部署操作
Deployment deploy = repositoryService.createDeployment()
// 关联要部署的流程文件
.addClasspathResource("请假流程-包容网关.bpmn20.xml")
.name("请假流程-包容网关-2023")
.deploy(); // 部署流程
System.out.println("deploy.getId() => " + deploy.getId());
System.out.println("deploy.getName() => " + deploy.getName());
}
static String PROC_DEF_ID = "qjlc-inclusive:1:4";
/**
* 运行流程实例
*/
@Test
public void test_run_proc() {
RuntimeService runtimeService = processEngine.getRuntimeService();
// 给流程定义中的UEL表达式赋值
Map<String, Object> params = new HashMap<>();
params.put("num", 3);
ProcessInstance processInstance = runtimeService.startProcessInstanceById(PROC_DEF_ID, params);
System.out.println("processInstance.getId() = " + processInstance.getId());
}
/**
* 任务完成
*/
@Test
public void complete_task() {
TaskService taskService = processEngine.getTaskService();
Task task = taskService.createTaskQuery().processDefinitionId(PROC_DEF_ID)
.taskCandidateOrAssigned("dy").singleResult();
if (task != null) {
taskService.complete(task.getId());
System.out.println("任务完成");
}
}
}
事件网关
事件网关允许根据事件判断流向。网关的每个外出顺序流都要连接到一个中间事件。当流程达到一个基于事件网关,网关会进入等待状态,暂停执行。同时会为每个外出顺序流创建相对的事件订阅。
事件网关的外出顺序流和普通顺序流不同,这些顺序流不会真的执行,相反他们流程引擎去决定指定到事件网关的流程需要订阅那些事件。需要考虑以下条件:
- 事件网关必须有两条或以上外出顺序流
- 事件网关后,只能使用intermediateCatchEvent类型
- 连接到事件网关的中间捕获事件必须只有一个入口顺序流。
1. 定时事件
定时触发的相关事件,包括定时器启动事件、定时器捕获中间事件、定时器边界事件。
1.1 定时器启动事件
定时器启动事件在指定时间创建流程实例。在流程只需要启动一次,或者流程需要在特定的时间间隔重复启动时,都可以使用。
注意:
1. 子流程不能有定时器启动事件。
2. 定时器启动事件,在流程部署的同事就开始计时。不需要调用startProcessInstanceByXXX就会定时启动。而调用startProcessInstanceByXXX方法,会另外启动一个新的流程实例。
3. 当部署带有定时器启动事件的流程更新版本的时候,上衣版本的定时器作业会被移除。这是因为通常并不希望旧版本的流程仍然自动启动新的流程实例。定时器启动时间,用一个钟表图标的圆圈来表示。
案例
- 绘制流程
在配置文件中开启定时任务
,默认是关闭的。
flowable:
async-executor-activate: true
参考:Flowable BPMN 用户手册——事件篇
最后
以上就是野性宝马为你收集整理的Flowable进阶学习(六)网关(排他网关、并行网关、包容网关、事件网关)排他网关并行网关包容网关事件网关的全部内容,希望文章能够帮你解决Flowable进阶学习(六)网关(排他网关、并行网关、包容网关、事件网关)排他网关并行网关包容网关事件网关所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复