文章目录
一、IDEA 中 Activiti BPMN visualizer 插件的安装
1、简介
Activiti 插件 actiBPM 在新版 idea 2020 中已不支持,这里找到一款替代的 Activiti BPMN visualizer
2、安装(设置-插件-搜索 Activiti BPMN visualizer)
3、解决中文乱码问题
在IDEA的安装目录,在 idea64.exe.vmoptions 文件中加上 -Dfile.encoding=UTF-8
help ——> Edit Custom VM options 加 -Dfile.encoding=UTF-8
配置完后重启 idea
二、相关配置
1、添加 pom 依赖
<dependencies>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter</artifactId>
<version>7.1.0.M6</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.31</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
</dependency>
</dependencies>
2、activiti.cfg.xml 文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans [
<!ELEMENT beans (bean)*>
<!ATTLIST beans
xmlns CDATA #REQUIRED
xmlns:xsi CDATA #REQUIRED
xsi:schemaLocation CDATA #REQUIRED>
<!ELEMENT bean (property)*>
<!ATTLIST bean
id CDATA #REQUIRED
class CDATA #REQUIRED>
<!ELEMENT property (#PCDATA)>
<!ATTLIST property
name CDATA #REQUIRED
value CDATA #REQUIRED>
]>
<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">
<!-- processEnqine Activiti 的流程引擎 -->
<bean id="processEngineConfiguration"
class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<property name="jdbcDriver" value="com.mysql.cj.jdbc.Driver"/>
<property name="jdbcUrl"
value="jdbc:mysql://localhost:3306/activiti?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false&nullCatalogMeansCurrent=true"/>
<property name="jdbcUsername" value="root"/>
<property name="jdbcPassword" value="123456"/>
<!-- activiti 数据库表处理策略 -->
<property name="databaseSchemaUpdate" value="true"/>
</bean>
</beans>
三、API 相关操作
1、Activiti 主要流程操作步骤
定义流程,按照BPMN的规范,使用流程定义工具,用流程符号把整个流程描述出来。
部署流程,把画好的流程定义文件,加载到数据库中,生成表的数据。
启动流程,使用 java 代码来操作数据库表中的内容。
操作流程当中的各个任务。
2、简单的请假流程
流程图
代码
/**
* 初始化数据库表:第一种方式
*/
@Test
public void testInitOne() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
System.err.println("processEngine = " + processEngine);
}
/**
* 初始化数据库表:第二种方式
*/
@Test
public void testInitTwo() {
ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml");
ProcessEngine processEngine = configuration.buildProcessEngine();
System.err.println("processEngine = " + processEngine);
}
/**
* 流程部署
*/
@Test
public void testDeploy() {
// 创建 ProcessEngine 对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取 repositoryService 对象
RepositoryService repositoryService = processEngine.getRepositoryService();
// 进行部署
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("process/test.bpmn20.xml")
.addClasspathResource("process/test.bpmn20.png")
.name("请假流程")
.deploy();
// 输出部署的一些信息
System.out.println("流程部署ID:" + deployment.getId());
System.out.println("流程部署名称:" + deployment.getName());
}
/**
* 启动流程实例
*/
@Test
public void testStartProcess() {
// 创建 ProcessEngine 对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取 runtimeService 对象
RuntimeService runtimeService = processEngine.getRuntimeService();
// 根据流程定义的key启动流程实例,这个key是在定义bpmn的时候设置的
ProcessInstance instance = runtimeService.startProcessInstanceByKey("test");
// 获取流程实例的相关信息
System.out.println("流程定义的id = " + instance.getProcessDefinitionId());
System.out.println("流程实例的id = " + instance.getId());
}
/**
* 查询待办任务
*/
@Test
public void testSelectTodoTaskList() {
String assignee = "李四";
// 创建 ProcessEngine 对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取指定用户审核任务
TaskService taskService = processEngine.getTaskService();
// 使用面对对象方式查询数据库
List<Task> tasks = taskService.createTaskQuery()
.processDefinitionKey("test")
.taskAssignee(assignee)
// 返回多个结果
.list();
// 只返回一个结果
// .singleResult();
// 自定义 sql 查询
// taskService.createNativeTaskQuery();
// 获取流程实例的相关信息
for (Task task : tasks) {
System.out.println("流程定义的id = " + task.getProcessDefinitionId());
System.out.println("流程实例的id = " + task.getProcessInstanceId());
System.out.println("任务id = " + task.getId());
System.out.println("任务名称 = " + task.getName());
}
}
/**
* 指定用户去完成任务待办:多人审批在这操作,改变审核人名称就行了
*/
@Test
public void testCompleteTask() {
String assignee = "李四";
// 创建 ProcessEngine 对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取指定用户审核任务
TaskService taskService = processEngine.getTaskService();
List<Task> tasks = taskService.createTaskQuery()
.processDefinitionKey("test")
.taskAssignee(assignee)
.list();
if (tasks != null && !tasks.isEmpty()){
// 当前流程图所限制,只能做审核同意的动作
for (Task task : tasks) {
taskService.complete(task.getId());
}
}
}
/**
* 审批添加备注
*/
@Test
public void testAddComment() {
String assignee = "张三";
// 创建 ProcessEngine 对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取指定用户审核任务
TaskService taskService = processEngine.getTaskService();
List<Task> tasks = taskService.createTaskQuery()
.processDefinitionKey("test")
.taskAssignee(assignee)
.list();
if (tasks != null && !tasks.isEmpty()) {
// 当前流程图所限制,只能做审核同意的动作
for (Task task : tasks) {
// 添加备注
taskService.addComment(task.getId(), task.getProcessInstanceId(), assignee + "表示同意");
taskService.complete(task.getId());
}
}
}
/**
* 查询审批历史
*/
@Test
public void testSelectHistoryTask() {
String processInstanceId = "2501";
String assignee = "张三";
// 创建 ProcessEngine 对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 查看历史信息
HistoryService historyService = processEngine.getHistoryService();
// 获取指定用户审核任务
TaskService taskService = processEngine.getTaskService();
// 获取历史审核信息
List<HistoricActivityInstance> userTask = historyService.createHistoricActivityInstanceQuery()
.activityType("userTask")
// 指定实例的id
.processInstanceId(processInstanceId)
.taskAssignee(assignee)
.finished()
.list();
for (HistoricActivityInstance instance : userTask) {
System.out.println("任务名称 = " + instance.getActivityName());
System.out.println("任务开始时间 = " + instance.getStartTime());
System.out.println("任务结束时间 = " + instance.getEndTime());
System.out.println("任务耗时 = " + instance.getDurationInMillis());
// 获取审批批注信息
List<Comment> taskComments = taskService.getTaskComments(instance.getTaskId());
if (!taskComments.isEmpty()){
System.out.println("审批批注 = " + taskComments.get(0).getFullMessage());
}
}
}
/**
* 查询流程相关信息
*/
@Test
public void testDefinitionQuery() {
// 创建 ProcessEngine 对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取仓库服务
RepositoryService repositoryService = processEngine.getRepositoryService();
// 获取流程定义集合
List<ProcessDefinition> processDefinitionList = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey("test")
// 最新的一个版本
.latestVersion()
.list();
// 遍历集合
for (ProcessDefinition definition : processDefinitionList) {
System.out.println("流程定义id = " + definition.getId());
System.out.println("流程定义名称 = " + definition.getName());
System.out.println("流程定义key = " + definition.getKey());
System.out.println("流程定义版本 = " + definition.getVersion());
System.out.println("流程部署id = " + definition.getDeploymentId());
System.out.println("===============");
}
}
/**
* 资源文件下载
*/
@Test
public void testDownloadResource() throws IOException {
// 创建 ProcessEngine 对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取仓库服务
RepositoryService repositoryService = processEngine.getRepositoryService();
// 获取流程定义集合
List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey("test")
// 按照版本降序
.orderByProcessDefinitionVersion()
// 降序
.desc()
.list();
// 获取最新那个
ProcessDefinition definition = list.get(0);
// 获取部署id
String deploymentId = definition.getDeploymentId();
// 获取bpmn的输入流
InputStream bpmnInputStream = repositoryService.getResourceAsStream(deploymentId, definition.getResourceName());
// 获取png的输入流
// InputStream pngInputStream = repositoryService.getResourceAsStream(deploymentId, definition.getDiagramResourceName());
String resourcePath = "C:/Users/ASUS/Desktop/" + File.separator + definition.getResourceName();
File file = new File(resourcePath);
if (!file.exists()) {
file.getParentFile().mkdirs();
}
String diagramResourcePath = "C:/Users/ASUS/Desktop/" + File.separator + definition.getDiagramResourceName();
file = new File(diagramResourcePath);
if (!file.exists()) {
file.getParentFile().mkdirs();
}
//复制文件
FileCopyUtils.copy(bpmnInputStream, Files.newOutputStream(Paths.get(resourcePath)));
// FileCopyUtils.copy(pngInputStream, Files.newOutputStream(Paths.get(diagramResourcePath)));
}
/**
* 删除已经部署的流程定义
*/
@Test
public void testDeleteDeploy() {
// 删除已经部署的流程定义
String deploymentId = "45001";
// 创建 ProcessEngine 对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取仓库服务
RepositoryService repositoryService = processEngine.getRepositoryService();
// 删除流程定义,如果改流程定义已有流程实例启动,则会报错
// repositoryService.deleteDeployment(deploymentId);
// 设置 true,级联删除流程定义,即使有启动的实例也可以删除
repositoryService.deleteDeployment(deploymentId, true);
}
/**
* 启动流程,需要进行 BusinessKey 绑定流程实例
*/
@Test
public void testStartBindBusinessKey() {
String businessKey = "1";
// 创建 ProcessEngine 对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();
// 根据流程定义的key启动流程实例,这个key是在定义bpmn的时候设置的
// 在启动流程的时候将业务key加进去
ProcessInstance instance = runtimeService.startProcessInstanceByKey("test", businessKey);
// 获取流程实例的相关信息
System.out.println("流程定义id = " + instance.getProcessDefinitionId());
System.out.println("流程实例id = " + instance.getId());
System.out.println("业务标识 = " + instance.getBusinessKey());
}
/**
* 跑到下一个节点,需要进行审批了,此时需要获取 BusinessKey 进而获取请假单信息
*/
@Test
public void testGetBusinessKey() {
// 1、获取李四的待办信息
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = processEngine.getTaskService();
List<Task> task = taskService.createTaskQuery()
.taskAssignee("李四")
.processDefinitionKey("test")
.list();
// 2、获取 businessKey
// 获取流程实例id
String processInstanceId = task.get(1).getProcessInstanceId();
RuntimeService runtimeService = processEngine.getRuntimeService();
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
.processInstanceId(processInstanceId)
.singleResult();
String businessKey = processInstance.getBusinessKey();
System.out.println("业务标识 = " + businessKey);
}
/**
* 流程定义挂起与激活
*/
@Test
public void testSuspendAllProcessInstance() {
// 创建 ProcessEngine 对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取仓库服务
RepositoryService repositoryService = processEngine.getRepositoryService();
// 获取流程定义对象
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey("test")
.singleResult();
boolean suspended = processDefinition.isSuspended();
// 输出流程定义状态
System.out.println("流程定义状态:" + (suspended ? "已挂起" : "已激活"));
String processDefinitionId = processDefinition.getId();
if (suspended) {
repositoryService.activateProcessDefinitionById(processDefinitionId, true, null);
System.out.println("流程id:" + processDefinitionId + "已激活");
} else {
repositoryService.suspendProcessDefinitionById(processDefinitionId, true, null);
System.out.println("流程id:" + processDefinitionId + "已挂起");
}
}
/**
* 流程实例挂起与激活
*/
@Test
public void testProcessInstance() {
// 创建 ProcessEngine 对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();
// 获取流程定义对象
List<ProcessInstance> processInstanceList = runtimeService.createProcessInstanceQuery()
.processDefinitionKey("test")
.list();
// 遍历集合
for (ProcessInstance processInstance : processInstanceList) {
boolean suspended = processInstance.isSuspended();
// 输出流程定义状态
System.out.println("流程实例状态:" + processInstance + "," + (suspended ? "已挂起" : "已激活"));
String processDefinitionId = processInstance.getId();
if (suspended) {
runtimeService.activateProcessInstanceById(processDefinitionId);
System.out.println("流程实例id:" + processDefinitionId + "已激活");
} else {
runtimeService.suspendProcessInstanceById(processDefinitionId);
System.out.println("流程实例id:" + processDefinitionId + "已挂起");
}
}
}
3、审批人是动态参数
流程图
代码
/**
* 流程部署
*/
@Test
public void testDeploy() {
// 创建 ProcessEngine 对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取 repositoryService 对象
RepositoryService repositoryService = processEngine.getRepositoryService();
// 进行部署
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("process/demo.bpmn20.xml")
.name("审批人是动态参数")
.deploy();
// 输出部署的一些信息
System.out.println("流程部署ID:" + deployment.getId());
System.out.println("流程部署名称:" + deployment.getName());
}
/**
* 启动流程实例
*/
@Test
public void testStartProcess() {
// 创建 ProcessEngine 对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取 runtimeService 对象
RuntimeService runtimeService = processEngine.getRuntimeService();
// key:uel变量名称, value:uel变量值
HashMap<String, Object> map = new HashMap<>();
map.put("day", "1");
// 根据流程定义的key启动流程实例,这个key是在定义bpmn的时候设置的
ProcessInstance instance = runtimeService.startProcessInstanceByKey("demo", map);
// 获取流程实例的相关信息
System.out.println("流程定义的id = " + instance.getProcessDefinitionId());
System.out.println("流程实例的id = " + instance.getId());
}
/**
* 启动流程实例--demo,审批人是动态参数
*/
@Test
public void demoStartProcess() {
// 创建 ProcessEngine 对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取 runtimeService 对象
RuntimeService runtimeService = processEngine.getRuntimeService();
// key:uel变量名称, value:uel变量值
HashMap<String, Object> map = new HashMap<>();
map.put("assignee0", "lisi");
map.put("assignee1", "zahngsan");
// 根据流程定义的key启动流程实例,这个key是在定义bpmn的时候设置的
ProcessInstance instance = runtimeService.startProcessInstanceByKey("demo", map);
// 获取流程实例的相关信息
System.out.println("流程定义的id = " + instance.getProcessDefinitionId());
System.out.println("流程实例的id = " + instance.getId());
}
4、分之流程,加判断条件
流程图
代码
/**
* 指定用户去完成任务待办:多人审批在这操作,改变审核人名称就行了--分支流程
*/
@Test
public void fenzhiCompleteTask() {
String assignee = "zhangsan";
// 创建 ProcessEngine 对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取指定用户审核任务
TaskService taskService = processEngine.getTaskService();
List<Task> tasks = taskService.createTaskQuery()
.processDefinitionKey("fenzhi")
.taskAssignee(assignee)
.list();
if (tasks != null && !tasks.isEmpty()){
// key:uel变量名称, value:uel变量值
HashMap<String, Object> map = new HashMap<>();
map.put("day", "1");
// 当前流程图所限制,只能做审核同意的动作
for (Task task : tasks) {
taskService.complete(task.getId(), map);
}
}
}
5、候选人相关操作
流程图
代码
/**
* 查询候选人待办任务--候选人
*/
@Test
public void houxuanrenSelectTodoTaskList() {
// 任务候选人
String candidateUser = "lisi";
// 创建 ProcessEngine 对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取指定用户审核任务
TaskService taskService = processEngine.getTaskService();
List<Task> tasks = taskService.createTaskQuery()
.taskCandidateUser(candidateUser)
.processDefinitionKey("houxuanren")
.list();
if (tasks != null && !tasks.isEmpty()){
for (Task task : tasks) {
System.out.println("流程定义的id = " + task.getProcessDefinitionId());
System.out.println("流程实例的id = " + task.getProcessInstanceId());
System.out.println("任务id = " + task.getId());
System.out.println("任务名称 = " + task.getName());
}
}
}
/**
* 领取候选人任务--候选人
*/
@Test
public void houxuanrenClaimTask() {
// 任务id
String taskId = "62505";
// 任务候选人
String candidateUser = "张三";
// 创建 ProcessEngine 对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取任务服务
TaskService taskService = processEngine.getTaskService();
// 指定人领取任务
taskService.claim(taskId, candidateUser);
// 如果反悔,不想领取任务
// taskService.claim(taskId, null);
}
/**
* 执行任务
*/
@Test
public void testCompleteTask() {
// 任务id
String taskId = "62505";
// 创建 ProcessEngine 对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取任务服务
TaskService taskService = processEngine.getTaskService();
// 指定人领取任务
taskService.complete(taskId);
}
6、排他网关
流程图,多个分之,只执行符合条件的一个分之
代码
/**
* 指定用户去完成任务待办:多人审批在这操作,改变审核人名称就行了--排他网关
*/
@Test
public void exclusiveGatewayCompleteTask() {
String assignee = "zhangsan";
// 创建 ProcessEngine 对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取指定用户审核任务
TaskService taskService = processEngine.getTaskService();
List<Task> tasks = taskService.createTaskQuery()
.processDefinitionKey("exclusivegateway")
.taskAssignee(assignee)
.list();
if (tasks != null && !tasks.isEmpty()){
// key:uel变量名称, value:uel变量值
HashMap<String, Object> map = new HashMap<>();
map.put("day", "3");
// 当前流程图所限制,只能做审核同意的动作
for (Task task : tasks) {
taskService.complete(task.getId(), map);
}
}
}
7、并行网关
流程图,多个分之,都要执行,才能执行下一步
8、包含网关
流程图,既有排他网关,也有并行网关