环境准备
JDK1.6或者更高版本
数据库: mysql8 (也可选h2,oracle, postgres, mssql, db2等)
一、安装流程设计器
1 打开File->Settings->Plugins,在右侧搜索框搜索Activiti BPMN visualizer。
重启IDEA,就可以创建bpmn文件
二、activiti配置
在pom文件中引入activiti7坐标,版本号为:7.0.0.Beta2,pom全文件如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.panghu.project</groupId>
<artifactId>activiti-test</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter</artifactId>
<version>7.0.0.Beta2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
添加application.yml配置:数据库信息对应成自己的即可
spring:
datasource:
username: root
password: root
url: jdbc:mysql://127.0.0.1:3306/activiti?characterEncoding=UTF-8&serverTimezone=UTC
driver-class-name: com.mysql.cj.jdbc.Driver
devtools:
restart:
enabled: true #设置开启热部署
activiti:
database-schema-update: true
history-level: full
db-history-used: true
debug: true
启动springboot,看控制台以及对应的数据库生成了对应的25张表
act_re_:’re’表示repository。带此前缀的表包含的是静态信息,如,流程定义,流程的资源(图片,规则等)。
act_ru_:’ru’表示runtime。这是运行时的表存储着流程变量,用户任务,变量,职责(job)等运行时的数据。activiti只存储实例执行期间的运行时数据,当流程实例结束时,将删除这些记录。这就保证了这些运行时的表小且快。
act_id_:’id’表示identity。这些表包含标识的信息,如用户,用户组,等等。
act_hi_:’hi’表示history。就是这些表包含着历史的相关数据,如结束的流程实例,变量,任务,等等。
act_ge_*:普通数据,各种情况都使用的数据。
1、act_ge_property:属性数据表。存储这个流程引擎级别的数据。
2、act_ge_bytearray:用来保存部署文件的大文本数据
3、act_re_deployment:用来存储部署时需要持久化保存下来的信息
4、act_re_procdef:业务流程定义数据表
注:此表和act_re_deployment是多对一的关系,即,一个部署的bar包里可能包含多个流程定义文件,每个流程定义文件都会有一条记录在act_reprocdef表内,每个流程定义的数据,都会对于act_ge_bytearray表内的一个资源文件和png图片文件。和act_ge_bytearray的关联是通过程序用act_ge_bytearray.name与act_re_procdef.name_完成的,在数据库表结构中没有体现。
5、act_ru_execution:流程执行记录。
6、act_ru_task:运行时任务数据表。
7、act_ru_identitylink:任务参与者数据表。主要存储当前节点参与者的信息。
8、act_ru_variable:运行时流程变量数据表。
9、act_hi_procinst:
10、act_hi_actinst:
11、act_hi_taskinst:
12、act_hi_detail:启动流程或者在任务complete之后,记录历史流程变量
13、act_hi_comment 意见表
流程文件部署主要涉及到3个表,分别是:act_ge_bytearray、act_re_deployment、act_re_procdef。主要完成“部署包”-->“流程定义文件”-->“所有包内文件”的解析部署关系。从表结构中可以看出,流程定义的元素需要每次从数据库加载并解析,因为流程定义的元素没有转化成数据库表来完成,当然流程元素解析后是放在缓存中的。
三、使用
先自定义创建一个流程
流程文件部署方式分为两种:自动部署和手动部署,将bpmn文件放到resources下的processes下,springboot启动时会自动部署,手动方式部署;在maven项目的测试文件夹下,新建测试类,并编写测试方法,进行流程文件部署,部署代码如下:
/**
* 涉及到的表
* act_ge_bytearray
* 1、说明
* 该表存储了bpmn文件和png图片
* 从字段可以看出,根据deploymentID可以查询bpmn文件和png图片
* 2、字段
* name_:存储该文件的路径名称
* deploymentid_id_:部署表的ID
* byte_:存放值(bpmn和png)
* act_re_deployment
* 1、说明
* 该表存储了部署的动作
* 2、字段
* ID_:部署ID 主键
* act_re_procdef
* 1、说明
* 流程定义表
* 2、字段
* id: 是由${name}:${version}:随机数 确定唯一的流程
* name_: 流程定义名称
* key_: 流程定义名称
* version_: 某一个流程定义的版本
* deployment_id_:部署表的ID
*
* 说明:
* 1、根据deploymentID-->查询图片和bpmn文件
* 2、根据deploymentID-->查询流程定义
* 3、只要流程名称不变,部署一次,版本号加1,id就发生变化,生成了一个新的deploymentID
* 4、所以deploymentID和pdid是一一对应的关系
*/
@Test
public void testDeployment(){
Deployment deployment = repositoryService.createDeployment().name("测试流程文件部署")
.addClasspathResource("test.bpmn")
.addClasspathResource("test.png").deploy();
log.info("部署id为:"+deployment.getId());
log.info("部署名称为:"+deployment.getName());
}
//获取部署的流程
@Test
public void getDeployment() {
List<Deployment> deploymentList = repositoryService.createDeploymentQuery().list();
if (!CollectionUtils.isEmpty(deploymentList)) {
deploymentList.stream().forEach(item -> {
log.info("部署id为:" + item.getId());
log.info("部署名称为:" + item.getName());
});
}
}
启动流程:根据流程定义的key启动流程
/**
* 启动流程实例
* 涉及到的表
* act_hi_actinst hi:history actinst:action instance
* 1、概念
* 所有的正在执行的或者已经完成的节点
* 2、字段
* act_type_:为节点的类型
* end_time_: 如果有值,说明该节点已经结束了
* act_hi_procinst procinst:process instance
* 1、概念
* 所有的正在执行的或者已经完成的流程实例
* 2、字段
* end_time_:如果该字段有值,说明这个流程实例已经结束了
* end_act_id_:说明该流程实例是在哪个节点结束的
* act_hi_taskinst taskinst:task instance
* 1、概念
* 所有的正在执行的或者已经完成的任务节点
* 2、字段
* end_time_:如果该字段有值,说明任务已经完成了
* delete_reason:如果该值为completed,说明该任务处于完成的状态
* act_ru_execution ru:runtime
* 1、概念
* 代表正在执行的流程实例
* 2、字段
* id_:主键 executionid
* proc_inst_id_: process instanceid
* proc_def_id_:pdid
* act_id_:当前的流程实例正在执行的节点的ID的值
* act_ru_task
* 1、概念
* 代表正在执行的任务
* 2、字段
* id_:主键 任务ID
* execution_id_:piid,executionid
* name_:任务名称
* 3、说明
* 该表是一个临时表,该表中的任务完成以后,这一行会被删除掉
*
*/
@Test
public void testStartProcess(){
String instanceKey = "test";
log.info("开启流程...");
Map<String, Object> map = new HashMap<String, Object>();
ProcessInstance instance = runtimeService.startProcessInstanceByKey(instanceKey, map);
log.info("启动流程实例成功:{}", instance);
log.info("流程实例ID:{}", instance.getId());
log.info("流程定义ID:{}", instance.getProcessDefinitionId());
}
//根据指定的任务办理人查询任务并办理
@Test
public void testGetTaskByAssignee(){
List<Task> tasks = taskService.createTaskQuery().taskAssignee("张三").list();
Map<String, Object> map = new HashMap<String, Object>();
map.put("fullMsg", "家中有事请假5天");
for (Task task : tasks) {
log.info("任务id为=="+task.getId());
taskService.complete(task.getId(),map);
}
}