概念

工作流(Work flow)

是指是通过计算机对业务流程自动化执行管理。它主要解决的是“使在多个参与者之间按照某种预定义的规则自动进行传递文档、信息或任务的过程,从而实现某个预期的业务目标,或者促使此目标的实现”。

示例(请假申请):

创造假期申请——》部门主管审批——》经理审批——》财务审批——》流程结束.

还有订单、报价处理、合同审核、供应链管理等众多适用场景。

BPMN2.0规范

BPMN(Business Process Model Notation——业务流程建模符号)是由BPMI(The Business Process Management Initiative)开发的一套标准的业务流程建模符号。使用BPMN提供的符号可创建所需的业务流程。——百度百科

中文版链接

Activiti 7.0

简介

Activiti是领先的轻量级、以 Java 为中心的开源 BPMN 引擎,支持现实世界的流程自动化需求。即是一个工作流引擎, Activiti可以将业务系统中复杂的业务流程抽取出来,使用专门的建模语言BPMN2.0进行定义,业务流程按照预先定义的流程进行执行,实现了系统的流程由Activiti进行管理,减少业务系统由于流程变更进行系统升级改造的工作量,从而提高系统的健壮性,同时也减少了系统开发维护成本。

历史

Alfresco软件在2010年5月17日宣布Activiti业务流程管理(BPM)开源项目的正式启动,其首席架构师由业务流程管理BPM的专家 Tom Baeyens担任,Tom Baeyens就是原来jbpm的架构师,而jbpm是一个非常有名的工作流引擎。

流程使用步骤

  1. 搭建Activiti部署环境:引入相应jar包,简单配置后使用Activiti的API在数据库创建表结构。
  2. 流程定义:使用流程建模工具定义业务流程(存储文件后缀.bpmn)。
  3. 流程定义部署: 使用Activiti提供的API把流程定义内容存储到数据库相关表中,后续操作Activiti可直接查询业务流程。
  4. 启动一个流程实例:即一次业务流程的运行。
  5. 完成用户任务:完成一个任务节点。
  6. 流程结束:当任务办理完成后没有下一个任务结点时,该流程结束。

准备

下载actiBPM插件

用于流程定义,新版IDEA找不到可直接去官网插件下载。装成功后新建会有BPMN File选项。

image-20210613014101946

数据库准备

Activiti运行需要有数据库的支持,使用25张表,把流程定义节点内容读取到数据库表中。支持的数据库有:h2, MySQL, oracle, postgres, mssql, db2。这里使用MySQL。

Activiti数据表介绍

表分类 表名 解释
一般数据
[ACT_GE_BYTEARRAY] 通用的流程定义和流程资源
[ACT_GE_PROPERTY] 系统相关属性
流程历史记录
[ACT_HI_ACTINST] 流程实例执行的历史信息
(任务+事件(如:startEvent、endEvent))
[ACT_HI_ATTACHMENT] 历史的流程附件
[ACT_HI_COMMENT] 历史的说明性信息
[ACT_HI_DETAIL] 历史的流程运行中的细节信息
[ACT_HI_IDENTITYLINK] 历史的流程运行过程中用户关系
[ACT_HI_PROCINST] 历史的流程实例
[ACT_HI_TASKINST] 历史的流程任务实例
[ACT_HI_VARINST] 历史的流程运行中的变量信息
流程定义表
[ACT_RE_DEPLOYMENT] 部署单元信息
[ACT_RE_MODEL] 模型信息
[ACT_RE_PROCDEF] 已部署的流程定义
运行实例表
[ACT_RU_EVENT_SUBSCR] 运行时事件
[ACT_RU_EXECUTION] 运行时流程执行实例
[ACT_RU_IDENTITYLINK] 运行时用户关系信息,存储任务节点与参与者的相关信息
(如:组管理中任务候选人信息)
[ACT_RU_JOB] 运行时作业
[ACT_RU_TASK] 运行时任务
[ACT_RU_VARIABLE] 运行时变量表

工作流程引擎(ProcessEngine)创建

创建数据库

1
CREATE DATABASE activiti DEFAULT CHARACTER SET utf8;--数据库名随意

引入maven依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!--activiti-engine中有依赖spring,会自动引入-->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-engine</artifactId>
<version>${activiti.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>

<!--日志 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>

创建流程引擎的配置类(ProcessEngineConfiguration)

可通过StandaloneProcessEngineConfiguration(默认)或SpringProcessEngineConfiguration与Spring整合两种方式创建ProcessEngineConfiguration。通过ProcessEngineConfiguration可以创建工作流引擎ProceccEngine,

  • 默认方式(配置文件名不可修改)
  1. 在resourse目录下创建activiti.cfg.xml配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 默认id对应的值 为processEngineConfiguration 不可改-->
<!-- processEngine Activiti的流程引擎 -->
<bean id="processEngineConfiguration"
class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<!-- activiti数据库表处理策略 已有表直接更新-->
<property name="databaseSchemaUpdate" value="true"/>

<property name="jdbcDriver" value="com.mysql.cj.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql:///activiti?serverTimezone=Asia/Shanghai"/>
<property name="jdbcUsername" value="root"/>
<property name="jdbcPassword" value="123456"/>

<!--也可引入连接池
<property name="dataSource" ref="dataSource"/>
-->
</bean>

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/activiti?serverTimezone=Asia/Shanghai"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
</beans>
  1. 创建流程引擎
1
2
3
4
5
6
7
public class CreateTables {
public static void main(String[] args) {
//使用classpath下的activiti.cfg.xml中的配置创建processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();//会创建表结构
System.out.println(processEngine);
}
}
  • 与spring结合(可自定义配置文件名)
  1. maven依赖
1
2
3
4
5
6
<!--     spring集成   -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring</artifactId>
<version>${activiti.version}</version>
</dependency>
  1. 在资源目录下创建配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd ">
<!-- 工作流引擎配置bean -->
<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
<!-- 数据源 -->
<property name="dataSource" ref="dataSource" />
<!-- 使用spring事务管理器 -->
<property name="transactionManager" ref="transactionManager" />
<!-- 数据库策略
drop-create:在创建流程引擎时创建模式,并在关闭流程引擎时删除模式。
false:在创建流程引擎时根据库检查数据库模式的版本,如果版本不匹配则抛出异常。
true:在构建流程引擎时,将执行检查并在必要时执行模式更新。
-->
<property name="databaseSchemaUpdate" value="true" />
</bean>
<!-- 流程引擎 -->
<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
<property name="processEngineConfiguration" ref="processEngineConfiguration" />
</bean>
<!-- 资源服务service -->
<bean id="repositoryService" factory-bean="processEngine"
factory-method="getRepositoryService" />
<!-- 流程运行service -->
<bean id="runtimeService" factory-bean="processEngine"
factory-method="getRuntimeService" />
<!-- 任务管理service -->
<bean id="taskService" factory-bean="processEngine"
factory-method="getTaskService" />
<!-- 历史管理service -->
<bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService" />
<!-- 引擎管理service -->
<bean id="managementService" factory-bean="processEngine" factory-method="getManagementService" />
<!-- 数据源 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/activiti?serverTimezone=Asia/Shanghai" />
<property name="username" value="root" />
<property name="password" value="123456" />
<property name="maxActive" value="3" />
</bean>
<!-- 事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 传播行为 -->
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="find*" propagation="SUPPORTS" read-only="true" />
<tx:method name="get*" propagation="SUPPORTS" read-only="true" />
</tx:attributes>
</tx:advice>
<!-- 切面-->
<aop:config>
<!-- 定义在service包和所有子包里的任意类的任意方法的执行-->
<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.czm.service..*.*(..))" />
</aop:config>
</beans>
  1. 创建流程引擎
1
2
3
4
5
6
7
8
9
10
11
@Slf4j
public class CreateTables {
public static void main(String[] args) {
//先构建ProcessEngineConfiguration, processEngineConfiguration名字与配置文件相对应,可自定义
ProcessEngineConfiguration configuration = ProcessEngineConfiguration
.createProcessEngineConfigurationFromResource
("MyActivitiConfig.xml","processEngineConfiguration");
//通过ProcessEngineConfiguration创建ProcessEngine,此时会创建数据库
ProcessEngine processEngine = configuration.buildProcessEngine();
}
}

流程定义

  1. 创建bpmn文件,设置流程定义Key为vacation,指定任务代理人(审批人)assignee。

image-20210613150221903

  1. 生成png流程图:

    将bpmn文件后缀改为xml,右键选择Diagrams生成并导出png图片,再将原来文件后缀改回bpmn。

注:

Activiti支持使用EL表达式对每个任务的assignee进行设置,在开启流程实例时可通过Map集合将流程变量传入,存储在ACT_RU_VARIABLE表中。也可用监听器的形式设置任务负责人——下面介绍。

可能遇到问题:

  1. 中文乱码:在IDEA的bin目录下的idea64.exe.vmoptions和idea.exe.vmoptions文件丽添加配置-Dfile.encoding=UTF-8
  2. 生产流程png文件时右键xml文件无Diagrams选项。再装个JBoss jBPM插件。
  3. 点击bpmn文件BPMN Editor未显示,修改idea主题为Light,再次点击即可显示。

image-20210613014438125

Service服务接口

简介

Service是工作流引擎提供用于进行工作流部署、执行、管理的服务接口,我们使用这些接口可以就是操作服务对应的数据表

Service总览

service名称 service作用
RepositoryService Activiti的资源管理类,可管理和控制流程发布包和流程定义
RuntimeService Activiti的流程运行管理类,可获取很多关于流程执行相关的信息
TaskService Activiti的任务管理类,可获取任务的信息。
HistoryService Activiti的历史管理类,查询历史信息,比如流程实例启动时间,任务的参与者, 完成任务的时间,每个流程实例的执行路径等。
ManagerService Activiti的引擎管理类,对 Activiti 流程引擎的管理和维护,主要用于 Activiti 系统的日常维护。

流程部署

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
@Slf4j
public class TestBase {
private ProcessEngine processEngine;

@Before
public void getProcessEngine() {
ProcessEngineConfiguration configuration = ProcessEngineConfiguration
.createProcessEngineConfigurationFromResource
("MyActivitiConfig.xml","processEngineConfiguration");
//通过ProcessEngineConfiguration创建ProcessEngine,此时会创建数据库
this.processEngine = configuration.buildProcessEngine();
// this.processEngine = ProcessEngines.getDefaultProcessEngine();
log.info("执行引擎processEngine:{}", processEngine);
}

/**
* 单独部署
*/
@Test
public void testDeployment(){
//获得 RepositoryService实例
RepositoryService repositoryService = processEngine.getRepositoryService();
//使用RepositoryService进行部署
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("bpmn/vacation.bpmn") // 添加bpmn资源
.addClasspathResource("bpmn/vacation.png") // 添加png资源
.name("请假申请流程")
.deploy();
log.info("流程部署id:" + deployment.getId());
log.info("流程部署名称:" + deployment.getName());
}

/**
* zip压缩包批量部署
*/
@Test
public void deployProcessByZip() {
// 定义zip输入流
InputStream inputStream = this
.getClass()
.getClassLoader()
.getResourceAsStream(
"bpmn/bpmn.zip");
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
// 获取repositoryService
RepositoryService repositoryService = processEngine
.getRepositoryService();
// 流程部署
Deployment deployment = repositoryService.createDeployment()
.addZipInputStream(zipInputStream)
.deploy();
log.info("流程部署id:" + deployment.getId());
log.info("流程部署名称:" + deployment.getName());
}

/**
* 删除流程部署
*/
@Test
public void deleteDeployment() {
// 通过流程引擎获取repositoryService
RepositoryService repositoryService = processEngine
.getRepositoryService();
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey("vacation")
.singleResult();
//删除流程定义,如果该流程定义已有流程实例启动则删除时出错
repositoryService.deleteDeployment(processDefinition.getDeploymentId());
//设置true 级联删除流程定义,即使该流程有流程实例启动也可以删除,设置为false非级联级别删除方式(默认)
//repositoryService.deleteDeployment(deploymentId, true);
}
}

在ACT_RE_PROCDEF表中可看到压缩包里的两个流程

image-20210613155448631

流程实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/**
* 启动流程实例
*/
@Test
public void testStartProcess(){
RuntimeService runtimeService = processEngine.getRuntimeService();
// 根据流程定义的id启动流程
ProcessInstance instance = runtimeService.startProcessInstanceByKey("vacation");
//businessKey与我们实际业务想关联,存在act_ru_execution表中, map存储的是要传递的变量,存储在ACT_RU_VARIABLE表中,可用EL表达式取出设置任务assignee
// Map<String, Object> map = new HashMap<String, Object>();
// map.put("assignee", "王五");
// runtimeService.startProcessInstanceByKey("vacation", "businessKey", map);
// 4、输出内容
log.info("流程定义ID:{}",instance.getProcessDefinitionId());
log.info("流程实例ID:{}",instance.getId());
log.info("当前活动的ID:{}",instance.getActivityId());
}
/**
* 完成个人任务
*/
@Test
public void completTask(){
TaskService taskService = processEngine.getTaskService();

Task task = taskService.createTaskQuery()
.processDefinitionKey("vacation")
.taskAssignee("张三")
//.list() 多个时使用
.singleResult();
// //完成jack的任务
// Task task2 = taskService.createTaskQuery()
// .processDefinitionKey("vacation")
// .taskAssignee("李四")
// .singleResult();
// // 完成rose的任务
// Task task3 = taskService.createTaskQuery()
// .processDefinitionKey("vacation")
// .taskAssignee("王五")
// .singleResult();


log.info("流程实例id={}",task.getProcessInstanceId());
log.info("任务Id={}",task.getId());
log.info("任务负责人={}",task.getAssignee());
log.info("任务名称={}",task.getName());
// 完成的任务
taskService.complete(task.getId());
}
/**
* 查询个人待执行的任务
*
*/
@Test
public void testFindPersonalTaskList(){
// 获取taskService
TaskService taskService = processEngine.getTaskService();
// 根据流程key 和 任务的负责人 查询任务
List<Task> taskList = taskService.createTaskQuery()
.processDefinitionKey("vacation") //流程Key
.taskAssignee("张三") //要查询的负责人
.list();
for (Task task : taskList) {
log.info("流程实例id={}",task.getProcessInstanceId());
log.info("任务Id={}",task.getId());
log.info("任务负责人={}",task.getAssignee());
log.info("任务名称={}",task.getName());
}
}

历史信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* 查看历史信息
*/
@Test
public void findHistoryInfo(){
HistoryService historyService = processEngine.getHistoryService();
// 获取 actinst表的查询对象
HistoricActivityInstanceQuery instanceQuery = historyService.createHistoricActivityInstanceQuery();
// 查询 actinst表,添加条件
instanceQuery.processDefinitionId(processEngine.getRepositoryService().createProcessDefinitionQuery().processDefinitionKey("vacation").singleResult().getId());
// 增加排序操作,orderByHistoricActivityInstanceStartTime 根据开始时间排序 asc 升序
instanceQuery.orderByHistoricActivityInstanceStartTime().asc();
// 查询所有内容
List<HistoricActivityInstance> activityInstanceList = instanceQuery.list();
// 输出
for (HistoricActivityInstance hi : activityInstanceList) {
log.info(hi.getActivityId());
log.info(hi.getActivityName());
log.info(hi.getProcessDefinitionId());
log.info(hi.getProcessInstanceId());
log.info("<==========================>");
}
}

资源下载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/**
* 下载 资源文件
* 方案1: 使用Activiti提供的api,来下载资源文件,保存到文件目录
* 方案2: 自己写代码从数据库中下载文件,使用jdbc对blob 类型,clob类型数据读取出来,保存到文件目录
* 解决Io操作:commons-io.jar
* 这里我们使用方案1,Activiti提供的api:RespositoryService
*/
@Test
public void getDeployment() throws IOException {
RepositoryService repositoryService = processEngine.getRepositoryService();
// 获取查询对象 ProcessDefinitionQuery查询流程定义信息
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey("vacation")
.singleResult();
// 通过流程定义信息,获取部署ID
String deploymentId = processDefinition.getDeploymentId();
// 通过RepositoryService ,传递部署id参数,读取资源信息(png 和 bpmn)
// 获取png图片的流
// 从流程定义表中,获取png图片的目录和名字
String pngName = processDefinition.getDiagramResourceName();
// 通过 部署id和 文件名字来获取图片的资源
InputStream pngInput = repositoryService.getResourceAsStream(deploymentId, pngName);
// 获取bpmn的流
String bpmnName = processDefinition.getResourceName();
InputStream bpmnInput = repositoryService.getResourceAsStream(deploymentId, bpmnName);
// 构造OutputStream流
File pngFile = new File("d:/vacation.png");
File bpmnFile = new File("d:/vacation.bpmn");
FileOutputStream pngOutStream = new FileOutputStream(pngFile);
FileOutputStream bpmnOutStream = new FileOutputStream(bpmnFile);
// 输入流,输出流的转换
IOUtils.copy(pngInput,pngOutStream);
IOUtils.copy(bpmnInput,bpmnOutStream);
// 关闭流
pngOutStream.close();
bpmnOutStream.close();
pngInput.close();
bpmnInput.close();
}

流程负责人设置(三种方式)

  1. 固定方式:前面已有。

  2. EL表达式

image-20210613234130451

  1. 监听器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.czm.listener;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.delegate.TaskListener;
import java.util.Objects;

/**
* @author CZM
* @create 2021/6/13
*/
@Slf4j
public class TestAssigneeListener implements TaskListener {

@Override
public void notify(DelegateTask delegateTask) {
log.info("delegateTask:{}", Objects.toString(delegateTask));
if("testListener".equals(delegateTask.getName()) && "create".equals(delegateTask.getEventName())) {
delegateTask.setAssignee("通过listener设置");
}
}
}

idea插件不知为啥设置不了,只能编辑文件配置监视器。

image-20210613234513819

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/**
* 测试设置任务负责人
*/
@Test
public void setAssagnee(){
//获得 RepositoryService实例
RepositoryService repositoryService = processEngine.getRepositoryService();
//使用RepositoryService进行部署
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("bpmn/testListener.bpmn") // 添加bpmn资源
.name("测试设置负责人")
.deploy();
log.info("流程部署id:" + deployment.getId());
log.info("流程部署名称:" + deployment.getName());
RuntimeService runtimeService = processEngine.getRuntimeService();
// 根据流程定义的id启动流程
//businessKey与我们实际业务想关联, map存储的是要传递的变量,存储在ACT_RU_VARIABLE表中,可用EL表达式取出设置任务assignee
Map<String, Object> variables = new HashMap<String, Object>();
variables.put("assigneeEL", "通过EL设置");
ProcessInstance instance = runtimeService.startProcessInstanceByKey("testListener", "businessKey", variables);
// 4、输出内容
log.info("流程定义ID:{}",instance.getProcessDefinitionId());
log.info("流程实例ID:{}",instance.getId());
log.info("当前活动的ID:{}",instance.getActivityId());

TaskService taskService = processEngine.getTaskService();

List<Task> taskList = taskService.createTaskQuery().processInstanceId(instance.getId()).list();
for (Task task : taskList) {
log.info("流程实例id={}",task.getProcessInstanceId());
log.info("任务Id={}",task.getId());
log.info("任务负责人={}",task.getAssignee());
log.info("任务名称={}",task.getName());
taskService.complete(task.getId());
}
}

网关

image-20210614172501904

作用:用来控制流程走向。

分类

  • 排他网关(ExclusiveGateway):只会选择条件为true的分支执行,若有多条true分支,选择id较小的执行。若都为false,则系统抛出异常。
  • 并行网关(ParallelGateway):将流程分成多条分支,也可以把多条分支汇聚到一起,再执行下一任务。注:并行网关不会解析条件。即使顺序流中定义了条件,也会被忽略。
  • 事件网关(EventGateway):网关的每个外出顺序流都要连接到一个中间捕获事件。根据它所连接的中间Catching事件来决定流程的走向。
  • 包含网关(InclusiveGateway):排他和并行网关的结和,只执行条件为true的分支(与排他的区别是可以执行多条分支)。多条true分支汇聚到一起,再会执行下一任务。

END