Activiti工作流

1.简介

Activiti项目是一项新的基于Apache许可的开源BPM平台,从基础开始构建,旨在提供支持新的BPMN 2.0标准。

Activiti是一种轻量级,可嵌入的BPM引擎,而且还设计适用于可扩展的云架构。 Activiti将提供宽松的Apache许可2.0,同时促进Activiti BPM引擎和BPMN 2.0的匹配。

2.Activiti的7大服务

  • RepositoryService:提供一系列管理流程部署和流程定义的API。

  • RuntimeService:在流程运行时对流程实例进行管理与控制。

  • TaskService:对流程任务进行管理,例如任务提醒、任务完成和创建任务等。

  • IdentityService:提供对流程角色数据进行管理的API,这些角色数据包括用户组、用户及它们之间的关系。

  • ManagementService:提供对流程引擎进行管理和维护的服务。

  • HistoryService:对流程的历史数据进行操作,包括查询、删除这些历史数据。

  • FormService:表单服务。

3.应用实例

3.1.开发组件

名称 版本
HighGoDB 安全版V4.5、企业版V5及以上
HgdbJdbc 6.2.4
JDK 1.6、1.7、1.8
Java IDE IntelliJ IDEA
SpringBoot 2.1.0.RELEASE
Activiti 7.0.0.Beta2

3.2.工程示例

image

3.3.主要文件

pom.xml

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.0.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.activiti/activiti-spring-boot-starter -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter</artifactId>
<version>7.0.0.Beta2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.highgo</groupId>
<artifactId>HgdbJdbc</artifactId>
<version>6.2.4</version>
</dependency>
</dependencies>

application.yml

spring:
datasource:
url: jdbc:highgo://xxxx:5866/activiti?currentSchema=activiti
username : sysdba
password : XXXX
driver-class-name: com.highgo.jdbc.Driver
activiti:
#1.flase:默认值。activiti在启动时,对比数据库表中保存的版本,如果没有表或者版本不匹配,将抛出异常
#2.true: activiti会对数据库中所有表进行更新操作。如果表不存在,则自动创建
#3.create_drop: 在activiti启动时创建表,在关闭时删除表(必须手动关闭引擎,才能删除表)
#4.drop-create: 在activiti启动时删除原来的旧表,然后在创建新表(不需要手动关闭引擎)
database-schema-update: true
#自动部署验证设置:true-开启(默认)、false-关闭 true时项目启动会自动部署
check-process-definitions: false
#注意,如果activiti后面加上了/,就要求启动的时候process文件夹中需要有流程定义文件
#是指定activiti流程描述文件的前缀(路径),启动时,activiti就会去寻找此路径下的流程描述文件,并且自动部署
process-definition-location-prefix: classpath:/processes/
# suffix 是一个String数组,表示描述文件的默认后缀名,默认**.bpmn和**.bpmn20.xml
# process-definition-location-suffixes:
# - **.bpmn
# - **.bpmn20.xml
# Activiti7历史数据无法自动插入,开启下面两个配置
# 检测历史表是否存在 activiti7默认没有开启数据库历史记录 启动数据库历史记录
db-history-used: true
#记录历史等级 可配置的历史级别有none, activity, audit, full
#none:不保存任何的历史数据,因此,在流程执行过程中,这是最高效的。
#activity:级别高于none,保存流程实例与流程行为,其他数据不保存。
#audit:除activity级别会保存的数据外,还会保存全部的流程任务及其属性。audit为history的默认值。
#full:保存历史数据的最高级别,除了会保存audit级别的数据外,还会保存其他全部流程相关的细节数据,包括一些流程参数等。
history-level: full
# 解决频繁查询SQL问题
async-executor-activate: false

leave.bpmn20.xml

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/processdef">
<process id="leave" name="leave" isExecutable="true">
<startEvent id="sid-4bb1b894-4189-4443-9d51-08408088e392"/>
<userTask id="sid-76b385e0-c375-40af-afbe-9623fe40ee7f" name="部门经理审批" activiti:assignee="${bm}"/>
<sequenceFlow id="sid-fbfc3fc7-99c7-46fd-9825-1f5d3fa6e82a" sourceRef="sid-4bb1b894-4189-4443-9d51-08408088e392" targetRef="sid-76b385e0-c375-40af-afbe-9623fe40ee7f"/>
<userTask id="sid-4a6bd0e8-285a-4770-b49d-5fa2f8dc698b" name="总经理审批" activiti:assignee="${gm}"/>
<sequenceFlow id="sid-d37f31eb-c958-4c5e-a834-3c48191d1091" sourceRef="sid-76b385e0-c375-40af-afbe-9623fe40ee7f" targetRef="sid-4a6bd0e8-285a-4770-b49d-5fa2f8dc698b"/>
<endEvent id="sid-9e1a9189-9194-4a79-86ba-8dcbb2280e31"/>
<sequenceFlow id="sid-b945400f-4bae-4f2e-b6e1-0d2083d4b028" sourceRef="sid-4a6bd0e8-285a-4770-b49d-5fa2f8dc698b" targetRef="sid-9e1a9189-9194-4a79-86ba-8dcbb2280e31"/>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_leave">
<bpmndi:BPMNPlane bpmnElement="leave" id="BPMNPlane_leave">
<bpmndi:BPMNShape id="shape-eaad1e5b-25df-445e-a846-7ed05e474f7e" bpmnElement="sid-4bb1b894-4189-4443-9d51-08408088e392">
<omgdc:Bounds x="-225.0" y="-60.0" width="30.0" height="30.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="shape-990f85eb-2522-47cf-963d-0f16efbe9011" bpmnElement="sid-76b385e0-c375-40af-afbe-9623fe40ee7f">
<omgdc:Bounds x="-130.0" y="-85.0" width="100.0" height="80.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="edge-b4d997db-6421-434c-b10f-285b7f28fc26" bpmnElement="sid-fbfc3fc7-99c7-46fd-9825-1f5d3fa6e82a">
<omgdi:waypoint x="-195.0" y="-45.0"/>
<omgdi:waypoint x="-130.0" y="-45.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="shape-b3139f61-0389-4cd6-ba9a-da6f41b22e9c" bpmnElement="sid-4a6bd0e8-285a-4770-b49d-5fa2f8dc698b">
<omgdc:Bounds x="40.0" y="-85.0" width="100.0" height="80.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="edge-2676f501-c646-4be0-9f69-325b55e2384e" bpmnElement="sid-d37f31eb-c958-4c5e-a834-3c48191d1091">
<omgdi:waypoint x="-30.0" y="-45.0"/>
<omgdi:waypoint x="40.0" y="-45.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="shape-55c9ee0f-8507-449d-abf2-459285170784" bpmnElement="sid-9e1a9189-9194-4a79-86ba-8dcbb2280e31">
<omgdc:Bounds x="195.0" y="-60.0" width="30.0" height="30.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="edge-ca8ae4f1-3bfd-4011-83e0-f864a8799213" bpmnElement="sid-b945400f-4bae-4f2e-b6e1-0d2083d4b028">
<omgdi:waypoint x="140.0" y="-45.0"/>
<omgdi:waypoint x="195.0" y="-45.0"/>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>

3.4.流程部署

3.4.1.自动部署

当 check-process-definitions:true 配置true时则为自动部署,需要把流程文件放到/processes/文件夹下。

3.4.2.手动部署
@Test
public void deployment(){
Deployment deployment = repositoryService.createDeployment()
.name("请假流程")
.addClasspathResource("processes/leave.bpmn20.xml")
.deploy();
System.out.println("流程ID:"+deployment.getId());
System.out.println("流程名称:"+deployment.getName());
}

日志打印输出

image

查看数据库表act_ge_bytearray中会增加一条数据,对应的就是刚刚新增的流程。

image

查看act_re_deployment

image

查看act_re_procdef

image

3.5.开启流程

@Test
public void startProcess(){
String processDefinitionKey = "leave";
String businessKey = "001";
Map<String,Object> map = new HashMap<>();
map.put("bm","张三");
ProcessInstance leave = runtimeService.startProcessInstanceByKey(processDefinitionKey,businessKey, map);
System.out.println("流程id:"+leave.getProcessDefinitionId());
System.out.println("流程实例id:"+leave.getId());
System.out.println("当前活动id:"+leave.getActivityId());
}

日志打印

image

因为是刚开始流程,所以没有人需要处理,当前活动id为null。这时查看act_hi_actinst就可以看到下一个需要处理的人。

image

3.6.查询任务

@Test
public void findTask(){
List<Task> taskList = taskService.createTaskQuery()
//流程实例key
.processDefinitionKey("leave")
//任务负责人
.taskAssignee("张三")
.list();
for (Task task : taskList) {
System.out.println("任务id:"+task.getId());
System.out.println("任务名称:"+task.getName());
System.out.println("任务负责人:"+task.getAssignee());
System.out.println("流程定义id:"+task.getProcessDefinitionId());
System.out.println("流程实例id:"+task.getProcessInstanceId());
System.out.println("任务创建时间:"+task.getCreateTime());
}
}

image

查询的数据来自表act_ru_task,需要注意的是act_ru_task 表中的数据只有需要处理的任务,一但任务完成,则会删除已完成任务的数据。

image

3.7.处理任务

@Test
public void dealTask(){
Map<String,Object> map = new HashMap<>();
map.put("gm","李四");
Task task = taskService.createTaskQuery()
// 流程id
.processDefinitionKey("leave")
// 处理人
.taskAssignee("张三")
.singleResult();
taskService.complete(task.getId(),map);
System.out.println("处理任务id:"+task.getId());
}

act_hi_actinst表中,处理时间已填充,并且添加了一下个处理人

image

act_ru_task表,zhangsan的数据不再了,新增了李四的数据

image

3.8.完成任务

任务处理只需重复执行上述方法即可,只是更改了任务的处理人,直至任务结束。

@Test
public void dealTask2() {
Task task = taskService.createTaskQuery()
// 流程id
.processDefinitionKey("leave")
// 处理人
.taskAssignee("李四")
.singleResult();
taskService.complete(task.getId());
System.out.println("处理任务id:"+task.getId());
}

3.9.获取流程处理历史

@Test
public void getHistoryList() {
List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery()
.processDefinitionId("leave:1:0079b147-ed6c-11ee-a186-64bc58439558")
.list();
for (HistoricTaskInstance historicTaskInstance : list) {
System.out.println("开始时间:" + historicTaskInstance.getStartTime());
System.out.println("流程名称:" + historicTaskInstance.getName());
System.out.println("处理人名称:" + historicTaskInstance.getAssignee());
System.out.println("结束时间:" + historicTaskInstance.getEndTime());
}
}

image