pom.xml
<dependencies>
<!-- 引入bootstrap依赖,不引入这个依赖是无法使用bootstrap配置文件的 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter</artifactId>
<version>${activiti.version}</version>
<exclusions>
<exclusion><!-- 排除activiti的mybatis,避免和外面的mybatis-plus冲突 -->
<artifactId>mybatis</artifactId>
<groupId>org.mybatis</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.activiti.dependencies</groupId>
<artifactId>activiti-dependencies</artifactId>
<version>${activiti.version}</version>
<type>pom</type>
</dependency>
<!-- 如果需要使用 Activiti 模型器,还需添加 modeler 依赖 -->
<!--<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-bpmn-modeler</artifactId>
<version>${activiti.version}</version>
</dependency>-->
<!--activiti可以绘制生成流程的的依赖-->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-image-generator</artifactId>
<version>${activiti.version}</version>
<exclusions>
<exclusion>
<artifactId>commons-io</artifactId>
<groupId>commons-io</groupId>
</exclusion>
<exclusion>
<artifactId>commons-lang3</artifactId>
<groupId>org.apache.commons</groupId>
</exclusion>
<exclusion>
<artifactId>commons-io</artifactId>
<groupId>commons-io</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- 数据库相关依赖 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<optional>true</optional>
</dependency>
<!-- hutool -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool-all.version}</version>
</dependency>
<!-- guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<!-- 新版jdk11以上已经没有@Resuorce注解 需要导入 -->
<!--<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>-->
<!-- fastjson2 -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>${fastjson2.version}</version>
</dependency>
</dependencies>
Activiti 使用到的表都是 ACT_
开头的,表名的第二部分表示用途。
-
ACT_GE_ (
GE
) 表示 general 全局通用数据及设置,各种情况都使用的数据。 -
ACT_HI_ (
HI
) 表示 history 历史数据表,包含着程执行的历史相关数据。 -
ACT_RE_ (
RE
) 表示 repository 存储,包含的是静态信息。 -
ACT_RU_ (
RU
) 表示 runtime 运行时,运行时的流程变量,用户任务,变量,职责(job)等运行时数据。Activiti 只存储实例执行期间的运行时数据,当流程实例结束时,将删除这些记录
全局通用数据(ACT_GE_*)#
表名 | 解释 |
---|---|
ACT_GE_BYTEARRAY | 二进制数据表,存储通用的流程定义和流程资源。 |
ACT_GE_PROPERTY | 系统相关属性,属性数据表存储整个流程引擎级别的数据。 |
历史数据表(ACT_HI_*)#
表名 | 解释 |
---|---|
ACT_HI_ACTINST | 历史节点表 |
ACT_HI_ATTACHMENT | 历史附件表 |
ACT_HI_COMMENT | 历史意见表 |
ACT_HI_DETAIL | 历史详情表,提供历史变量的查询 |
ACT_HI_IDENTITYLINK | 历史流程人员表 |
ACT_HI_PROCINST | 历史流程实例表 |
ACT_HI_TASKINST | 历史任务实例表 |
ACT_HI_VARINST | 历史变量表 |
静态信息表(ACT_RE_*)#
表名 | 解释 |
---|---|
ACT_RE_DEPLOYMENT | 部署信息表 |
ACT_RE_MODEL | 流程设计模型部署表 |
ACT_RE_PROCDEF | 流程定义数据表 |
运行数据(ACT_RU_*)#
表名 | 解释 |
---|---|
ACT_RU_DEADLETTER_JOB | 无法执行工作表: 如果一个任务执行了很多次,都无法执行,那么这个任务会写到 |
ACT_RU_EVENT_SUBSCR | 运行时事件 throwEvent、catchEvent 时间监听信息表 |
ACT_RU_EXECUTION | 运行时流程执行实例 |
ACT_RU_IDENTITYLINK | 运行时流程人员表,主要存储任务节点与参与者的相关信息 |
ACT_RU_INTEGRATION | 运行时积分表 |
ACT_RU_JOB | 运行时定时任务数据表 |
ACT_RU_SUSPENDED_JOB | 暂停的工作,流程中有一个定时任务,如果把这个任务停止工作了,这个任务会在act_ru_suspended_job中写入数据 |
ACT_RU_TASK | 运行时任务节点表 |
ACT_RU_TIMER_JOB | 运行时定时器作业表 |
ACT_RU_VARIABLE | 运行时流程变量数据表 |
其它表#
表名 | 解释 |
---|---|
ACT_EVT_LOG | 事件日志 |
ACT_PROCDEF_INFO | 流程定义的动态变更信息 |
快速入门#
流程部署#
流程部署方式分为两种:自动部署与手动部署
自动部署:将 bpmn
文件放入 resources
资源目录下的 processes
文件夹中,项目启动时则进行自动部署。
spring:
# activiti7配置
activiti:
# 自动部署验证设置:true-开启(默认)、false-关闭
check-process-definitions: true
# 保存历史数据
history-level: full
# 检测历史表是否存在
db-history-used: true
# 关闭SpringAutoDeployment
deployment-mode: never-fail
# 对数据库中所有表进行更新操作,如果表不存在,则自动创建
database-schema-update: true
# 解决频繁查询SQL问题
async-executor-activate: false
手动部署:新建测试类,并编写流程部署测试方法。
自定流程#
- 创建 *.bpmn20.xml 文件:New -> New Activity 6.x BPMN 2.x file
- 流程设计页面:选中
*.bpmn20.xml
文件,右键view BPMN(Activity ) Diagram
<?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="Part1_Deployment" name="Part1_Deployment" isExecutable="true">
<startEvent id="sid-26d6e725-878e-411d-b23d-6df4ae3cbd24"/>
<endEvent id="sid-03d64ced-963c-4506-a5b3-21b8a9dc4279"/>
<userTask id="sid-192966db-031d-4a50-886d-379935dd9bc1" name="UserTask" activiti:assignee="admin"/>
<sequenceFlow id="sid-560ce1e7-a0f9-4a99-8a64-d2920292cd37" sourceRef="sid-26d6e725-878e-411d-b23d-6df4ae3cbd24" targetRef="sid-192966db-031d-4a50-886d-379935dd9bc1"/>
<sequenceFlow id="sid-da2d1cc1-7544-40f6-81ab-1d0c32c0064a" sourceRef="sid-192966db-031d-4a50-886d-379935dd9bc1" targetRef="sid-03d64ced-963c-4506-a5b3-21b8a9dc4279"/>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_Part1_Deployment">
<bpmndi:BPMNPlane bpmnElement="Part1_Deployment" id="BPMNPlane_Part1_Deployment">
<bpmndi:BPMNShape id="shape-6b3bc939-03fe-47d7-b1fb-44a959045633" bpmnElement="sid-26d6e725-878e-411d-b23d-6df4ae3cbd24">
<omgdc:Bounds x="-20.0" y="-85.0" width="30.0" height="30.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="shape-8137d303-1a5b-4a34-b8d7-995a29ae534a" bpmnElement="sid-03d64ced-963c-4506-a5b3-21b8a9dc4279">
<omgdc:Bounds x="-20.0" y="105.00001" width="30.0" height="30.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="shape-40199472-3308-4677-9a38-067b57a4a17b" bpmnElement="sid-192966db-031d-4a50-886d-379935dd9bc1">
<omgdc:Bounds x="-55.0" y="-15.0" width="100.0" height="80.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="edge-05926a76-90de-4b3f-8fd5-d27d06dd6d6e" bpmnElement="sid-560ce1e7-a0f9-4a99-8a64-d2920292cd37">
<omgdi:waypoint x="-5.0" y="-55.0"/>
<omgdi:waypoint x="-5.0" y="-15.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="edge-6b52ec5d-0f90-4972-a304-022f03ccf3cf" bpmnElement="sid-da2d1cc1-7544-40f6-81ab-1d0c32c0064a">
<omgdi:waypoint x="-5.0" y="65.0"/>
<omgdi:waypoint x="-5.0" y="105.00001"/>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
单元测试#
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.InputStream;
import java.util.List;
import java.util.zip.ZipInputStream;
@SpringBootTest
public class DeploymentTest {
@Autowired
private RepositoryService repositoryService;
/**
* 流程部署
*/
@Test
public void initDeployment() {
String fileName = "bpmn/Part1_Deployment.bpmn20.xml";
Deployment deployment = this.repositoryService.createDeployment()
.addClasspathResource(fileName)
.name("流程部署测试")
.deploy();
System.out.println("流程部署名称:" + deployment.getName());
}
/**
* 流程部署(Zip包)
*/
@Test
public void initDeploymentByZip() {
InputStream inputStream = this.getClass()
.getClassLoader()
.getResourceAsStream("bpmn/Part1_Deployment.zip");
assert inputStream != null;
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
Deployment deployment = this.repositoryService.createDeployment()
.addZipInputStream(zipInputStream)
.name("流程部署测试(Zip包)")
.deploy();
System.out.println("流部署名称:" + deployment.getName());
}
/**
* 查询流程部署列表
*/
@Test
public void listDeployments() {
List<Deployment> deployments = this.repositoryService.createDeploymentQuery().list();
if (!deployments.isEmpty()) {
deployments.forEach(deployment -> {
System.out.println("Id:" + deployment.getId());
System.out.println("Name:" + deployment.getName());
System.out.println("DeploymentTime:" + deployment.getDeploymentTime());
System.out.println("Key:" + deployment.getKey());
});
}
}
/**
* 删除对流程实例、历史流程实例和作业的给定部署和级联删除
*/
@Test
public void deleteDeployment() {
String deploymentId = "4c97f9ce-4774-11ed-930a-e4a8dfd43d4a";
this.repositoryService.deleteDeployment(deploymentId, false);
}
}
涉及数据表:act_re_deployment、act_re_procdef、act_ge_bytearray
act_re_deployment 和 act_re_procdef 属于一对多关系,即:一次部署可以部署多个流程定义,而只会在 act_re_deployment 生成一条记录
流程定义#
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.ProcessDefinition;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.util.CollectionUtils;
import java.util.List;
@SpringBootTest
public class ProcessDefinitionTest {
@Autowired
private RepositoryService repositoryService;
/**
* 查询流程定义列表
*/
@Test
public void listProcessDefinitions() {
List<ProcessDefinition> processDefinitions = this.repositoryService.createProcessDefinitionQuery()
.list();
if (!CollectionUtils.isEmpty(processDefinitions)) {
processDefinitions.forEach(processDefinition -> {
System.out.println("Name:" + processDefinition.getName());
System.out.println("Key:" + processDefinition.getKey());
System.out.println("ResourceName:" + processDefinition.getResourceName());
System.out.println("DeploymentId:" + processDefinition.getDeploymentId());
System.out.println("Version:" + processDefinition.getVersion());
});
}
}
}
流程实例#
注意:流程定义(ProcessDefinition)与流程实例(ProcessInstance)是一对多关系
import org.activiti.engine.RuntimeService;
import org.activiti.engine.runtime.ProcessInstance;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.util.CollectionUtils;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@SpringBootTest
public class ProcessInstanceTest {
@Autowired
private RuntimeService runtimeService;
/**
* 初始化流程实例
*/
@Test
public void initProcessInstance() {
// 流程定义KEY
String processDefinitionKey = "Part1_Deployment";
// 业务表KEY(用于把业务数据与Activiti7流程数据相关联)
String businessKey = "4208169753200945";
// 参数
Map<String, Object> variables = new HashMap<>(16);
ProcessInstance processInstance = this.runtimeService
.startProcessInstanceByKey(processDefinitionKey, businessKey, variables);
System.out.println("流程实例ID:" + processInstance.getProcessInstanceId());
}
/**
* 查询流程实例
*/
@Test
public void getProcessInstance() {
String processInstanceId = "354709ac-477f-11ed-abfa-e4a8dfd43d4a";
ProcessInstance processInstance = this.runtimeService.createProcessInstanceQuery()
.processInstanceId(processInstanceId)
.singleResult();
System.out.println("ProcessInstanceId:" + processInstance.getProcessInstanceId());
System.out.println("ProcessDefinitionId:" + processInstance.getProcessDefinitionId());
System.out.println("isEnded:" + processInstance.isEnded());
System.out.println("isSuspended:" + processInstance.isSuspended());
}
/**
* 查询流程实例列表
*/
@Test
public void listProcessInstances() {
List<ProcessInstance> processInstanceList = this.runtimeService.createProcessInstanceQuery().list();
if (!CollectionUtils.isEmpty(processInstanceList)) {
processInstanceList.forEach(processInstance -> {
System.out.println("ProcessInstanceId:" + processInstance.getProcessInstanceId());
System.out.println("ProcessDefinitionId:" + processInstance.getProcessDefinitionId());
System.out.println("isEnded:" + processInstance.isEnded());
System.out.println("isSuspended:" + processInstance.isSuspended());
});
}
}
/**
* 挂起流程实例
*/
@Test
public void suspendProcessInstance() {
String processInstanceId = "354709ac-477f-11ed-abfa-e4a8dfd43d4a";
this.runtimeService.suspendProcessInstanceById(processInstanceId);
}
/**
* 激活流程实例
*/
@Test
public void activeProcessInstance() {
String processInstanceId = "354709ac-477f-11ed-abfa-e4a8dfd43d4a";
this.runtimeService.activateProcessInstanceById(processInstanceId);
}
/**
* 删除流程实例
*/
@Test
public void deleteProcessInstance() {
String processInstanceId = "354709ac-477f-11ed-abfa-e4a8dfd43d4a";
String reason = "测试删除流程实例";
this.runtimeService.deleteProcessInstance(processInstanceId, reason);
}
}
涉及数据表:act_hi_actinst、act_hi_taskinst、act_hi_identitylink、act_hi_procinst、act_ru_execution、act_ru_identitylink、act_ru_task
任务管理#
- Assignee:执行人/代理人
- Candidate Users:候选人
- Candidate Groups:候选组
- Due Date:任务到期时间
import org.activiti.engine.TaskService;
import org.activiti.engine.task.Task;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.util.CollectionUtils;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@SpringBootTest
public class TaskTest {
@Autowired
private TaskService taskService;
/**
* 查询任务列表
*/
@Test
public void listTasks() {
List<Task> taskList = this.taskService.createTaskQuery().list();
if (!CollectionUtils.isEmpty(taskList)) {
taskList.forEach(task -> {
System.out.println("Id:" + task.getId());
System.out.println("Name:" + task.getName());
System.out.println("Assignee:" + task.getAssignee());
});
}
}
/**
* 查询我的代办任务
*/
@Test
public void listTasksByAssignee() {
String assignee = "admin";
List<Task> taskList = this.taskService.createTaskQuery()
.taskAssignee(assignee)
.list();
if (!CollectionUtils.isEmpty(taskList)) {
taskList.forEach(task -> {
System.out.println("Id:" + task.getId());
System.out.println("Name:" + task.getName());
System.out.println("Assignee:" + task.getAssignee());
});
}
}
/**
* 完成任务
*/
@Test
public void completeTask() {
String taskId = "354b9d90-477f-11ed-abfa-e4a8dfd43d4a";
Map<String, Object> variables = new HashMap<>(16);
this.taskService.complete(taskId, variables);
}
/**
* 拾取任务
*/
@Test
public void claimTask() {
String taskId = "16beabc1-479f-11ed-9c3a-e4a8dfd43d4a";
String userId = "jason";
Task task = this.taskService.createTaskQuery().taskId(taskId).singleResult();
taskService.claim(taskId, userId);
}
/**
* 归还任务
*/
@Test
public void returnTask() {
String taskId = "16beabc1-479f-11ed-9c3a-e4a8dfd43d4a";
Task task = this.taskService.createTaskQuery().taskId(taskId).singleResult();
// 归还任务
taskService.unclaim(taskId);
}
/**
* 交办任务
*/
@Test
public void handoverTask() {
String taskId = "16beabc1-479f-11ed-9c3a-e4a8dfd43d4a";
String userId = "jack";
Task task = this.taskService.createTaskQuery().taskId(taskId).singleResult();
// 交办任务
taskService.setAssignee(taskId, userId);
}
}
涉及数据表:act_hi_actinst、act_hi_taskinst、act_hi_identitylink、act_hi_procinst、act_ru_execution、act_ru_identitylink、act_ru_task
历史记录#
import org.activiti.engine.HistoryService;
import org.activiti.engine.history.HistoricTaskInstance;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.util.CollectionUtils;
import java.util.List;
@SpringBootTest
public class HistoricTest {
@Autowired
private HistoryService historyService;
/**
* 根据用户名查询历史记录
*/
@Test
public void listHistoricTasksByAssignee() {
String assignee = "admin";
List<HistoricTaskInstance> historicTasks = this.historyService.createHistoricTaskInstanceQuery()
.orderByHistoricTaskInstanceEndTime()
.asc()
.taskAssignee(assignee)
.list();
if (!CollectionUtils.isEmpty(historicTasks)) {
historicTasks.forEach(historicTaskInstance -> {
System.out.println("Id:" + historicTaskInstance.getId());
System.out.println("ProcessInstanceId:" + historicTaskInstance.getProcessInstanceId());
System.out.println("Name:" + historicTaskInstance.getName());
});
}
}
/**
* 根据流程实例ID查询历史
*/
@Test
public void listHistoricTasksByProcessInstanceId() {
String processInstanceId = "0f8a9b00-479e-11ed-af85-e4a8dfd43d4a";
List<HistoricTaskInstance> historicTasks = this.historyService.createHistoricTaskInstanceQuery()
.orderByHistoricTaskInstanceEndTime()
.asc()
.processInstanceId(processInstanceId)
.list();
if (!CollectionUtils.isEmpty(historicTasks)) {
historicTasks.forEach(historicTaskInstance -> {
System.out.println("Id:" + historicTaskInstance.getId());
System.out.println("ProcessInstanceId:" + historicTaskInstance.getProcessInstanceId());
System.out.println("Name:" + historicTaskInstance.getName());
});
}
}
}
UEL表达式#
- 表达式以
${
开始;}
结束,例如:$ - 支持逻辑运算:$
- 支持变量(变量名必须小写)与实体类赋值
涉及数据表:act_hi_varinst、act_ru_variable
BPMN2.0网关#
并行网关(Parallel gateway)#
注意:并行网关有开始就要有结束
排他网关(Exclusive gateway)#
包容网关(Inclusive gateway)#
注意:包容网关是并行网关的一种衍生,所以也是成对出现
事件网关(Event gateway)#
作者:mountainstudy
出处:https://www.cnblogs.com/mountainstudy/p/17953905
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。