目录
文章目录
- 目录
- 准备Activiti建模工具
- 1、BPMN-js在线设计器
- 1.1 安装
- 1.2 使用说明
- 1.3运行截图
- 2、IDEA安装Activiti Designer插件
- 2.1安装插件
- 2.2 设置编码格式防止中文乱码
- 2.3 截图
- 简单工作流入门实例
- 1. 新建Spring Boot工程
- 2. 引入Activiti相关依赖
- 添加版本属性
- 指定仓库
- 添加依赖
- 完整的pom文件
- 3.配置数据库
- 添加MySQL依赖
- 修改配置文件
- 4.配置application.yml文件清单
- 4启动SpringBoot
- 5.新建流程
- 绘制流程
- 生成png图像
- 部署工作流程
- 启动一个流程实例
- 任务查询
- 任务处理
- 查询历史
准备Activiti建模工具
这里可以使用两种建模工具:bpmn.js和 IDEA的插件
1、BPMN-js在线设计器
bpmn.js是一个BPMN2.0渲染工具包和web建模器。
1.1 安装
需要使用到nodejs环境
1.1. 1 切换到项目目录下运行 npm install 安装依赖,也可以使用
cnpm install
1.1.2. 运行 npm run dev 启动
npm run dev
1.2 使用说明
可在页面进行拖拽设计 activiti 的流程图,支持导出 bpmn 流程图和 svg 图片
1.3运行截图
2、IDEA安装Activiti Designer插件
2.1安装插件
在IDEA的File菜单中找到子菜单”Settings”,后面我们再选择左侧的“plugins”菜单,搜索actiBPM插件。
重启IDEA就可以使用了。
2.2 设置编码格式防止中文乱码
更改idea配置文件, 否则工作流中输入中文会乱码
- 进入idea安装目录的bin文件夹下, 找到idea.exe.vmoptions与idea64.exe.vmoptions两个文件
- 在两个文件的最后加入 -Dfile.encoding=UTF-8
2.3 截图
简单工作流入门实例
这里使用 SpringBoot+Activiti 实现一个最基础的工作流
1. 新建Spring Boot工程
打开IDEA创建一个SpringBoot项目
输入组织名,包名,打包方式jar,创建Maven项目,java版本8
选择要使用的组件,你可以在这里选择自己需要的,在生成最终的项目时会自动加入到maven中。
2. 引入Activiti相关依赖
添加版本属性
<properties>
<java.version>1.8</java.version>
<activiti.version>7.1.0.M6</activiti.version>
</properties>
声明依赖版本
<!-- 声明依赖-->
<dependencyManagement>
<dependencies>
<!-- 声明activiti依赖的版本-->
<dependency>
<groupId>org.activiti.dependencies</groupId>
<artifactId>activiti-dependencies</artifactId>
<version>${activiti.version}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
指定仓库
添加私服仓库地址,不然容易出现无法下载包的问题
<!--指定仓库-->
<repositories>
<!-- activiti仓库 -->
<repository>
<id>alfresco</id>
<name>Activiti Releases</name>
<url>https://artifacts.alfresco.com/nexus/content/repositories/activiti-releases/</url>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>
添加依赖
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter</artifactId>
</dependency>
完整的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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.ts</groupId>
<artifactId>springboot_activiti_demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot_activiti_demo</name>
<description>Spring Boot + Activiti实例</description>
<properties>
<java.version>1.8</java.version>
<activiti.version>7.1.0.M6</activiti.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter</artifactId>
<version>${activiti.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- 生成图片 -->
<!--<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-image-generator</artifactId>
</dependency>-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.48</version>
<scope>runtime</scope>
</dependency>
<!-- 连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
<!-- Thymeleaf依赖 -->
<!--<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<!--指定仓库-->
<repositories>
<!-- activiti仓库 -->
<repository>
<id>alfresco</id>
<name>Activiti Releases</name>
<url>https://artifacts.alfresco.com/nexus/content/repositories/activiti-releases/</url>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>
<!-- 声明依赖-->
<dependencyManagement>
<dependencies>
<!-- 声明activiti依赖的版本-->
<!--<dependency>
<groupId>org.activiti.dependencies</groupId>
<artifactId>activiti-dependencies</artifactId>
<version>${activiti.version}</version>
<scope>import</scope>
<type>pom</type>
</dependency>-->
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3.配置数据库
添加MySQL依赖
在正常使用中,一般系统会有自己的数据库,而不会采用Activiti默认内存的数据库H2,这里使用MySQL数据库。
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.48</version>
<scope>runtime</scope>
</dependency>
修改配置文件
修改application.yml文件
spring :
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/activiti?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC&nullCatalogMeansCurrent=true
#url: jdbc:mysql://127.0.0.1:3306/activiti?useUnicode=true&characterEncoding=utf-8&serverTimezone=CTT&useSSL=false
username: root
password: root
type: com.alibaba.druid.pool.DruidDataSource
initialization-mode: always
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
filters: stat,wall,log4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
Activiti相关配置
修改application.yml文件
activiti:
# 自动建表
#database-schema: activiti
database-schema-update: true
history-level: full
db-history-used: true
database-schema-update表示启动时检查数据库表,不存在则创建
history-level表示哪种情况下使用历史表,这里配置为full表示全部记录历史,方便绘制流程图
db-history-used为true表示使用历史表,如果不配置,历史表没有建立,则流程图及运行节点无法展示
4.配置application.yml文件清单
spring :
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/testactiviti?useUnicode=true&characterEncoding=utf-8&serverTimezone=CTT&useSSL=false
username: root
password: root
type: com.alibaba.druid.pool.DruidDataSource
initialization-mode: always
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
filters: stat,wall,log4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
# mvc:
# 静态资源
# static-path-pattern: /static/**
# thymeleaf:
# mode: HTML
# encoding: utf-8
# #关闭缓存
# cache: false
activiti:
#1.flase: 默认值。activiti在启动时,会对比数据库表中保存的版本,如果没有表或者版本不匹配,将抛出异常
#2.true: activiti会对数据库中所有表进行更新操作。如果表不存在,则自动创建
#3.create_drop: 在activiti启动时创建表,在关闭时删除表(必须手动关闭引擎,才能删除表)
#4.drop-create: 在activiti启动时删除原来的旧表,然后在创建新表(不需要手动关闭引擎)
database-schema-update: true
#记录历史等级 可配置的历史级别有none, activity, audit, full
history-level: full
#检测历史表是否存在
db-history-used: true
#校验流程文件,默认校验resources下的processes文件夹里的流程文件
check-process-definitions: false
4启动SpringBoot
启动SpringBoot工程,生成表(25张)
5.新建流程
创建bpmn工作流文件
首先选中存放图形的目录(选择resources下的bpmn目录),点击菜单:New-BpmnFile
绘制流程
绘制完成以后修改id和name,然后指定任务负责人
生成png图像
复制bpmn_test.bpmn并更名bpmn_test.xml
右键选中Diagrams–》show BPMN2.0
点击Export to file ,然后放在resources下的bpmn目录下就可以了。
部署工作流程
要将上边绘制的图形即流程定义(.bpmn)部署在工作流程引擎activiti中
创建一个测试类ActivitiTest
package com.ts;
//import org.activiti.api.process.runtime.ProcessRuntime;
//import org.activiti.engine.ProcessEngine;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/**
* 流程测试类
* @author ZQ
* @date 2020/11/23 0019 15:16
**/
@RunWith(SpringRunner.class)
@SpringBootTest
public class ActivitiTest {
//@Autowired
//private ProcessRuntime processRuntime;
//@Autowired
//private ProcessEngine processEngine;
@Autowired
private RepositoryService repositoryService;
private static final Logger log = LoggerFactory.getLogger(ActivitiTest.class);
/**
* 流程定义的部署
* activiti相关表
* act_re_deployment 部署信息
* act_re_procdef 流程定义的一些信息
* act_ge_bytearray 流程定义的bpmn文件及png文件
*/
@Test
public void createDeploy() {
//RepositoryService repositoryService = processEngine.getRepositoryService();
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("bpmn/bpmn_test.bpmn")//添加bpmn资源
.addClasspathResource("bpmn/bpmn_test.png")
.name("请假申请单流程")
.deploy();
log.info("流程部署id:" + deployment.getName());
log.info("流程部署名称:" + deployment.getId());
}
}
执行此操作后activiti会将上边代码中指定的bpm文件和图片文件保存在activiti数据库。
启动一个流程实例
流程定义部署在activiti后就可以通过工作流管理业务流程了,也就是说上边部署的请假申请流程可以使用了。
针对该流程,启动一个流程表示发起一个新的请假申请单,这就相当于java类与java对象的关系,类定义好后需要new创建一个对象使用,当然可以new多个对象。
对于请假申请流程,张三发起一个请假申请单需要启动一个流程实例,李四发起一个请假单也需要启动一个流程实例。
/**
* 2
* 启动流程实例:
* 前提是先已经完成流程定义的部署工作
* <p>
* 背后影响的表:
* act_hi_actinst 已完成的活动信息
* act_hi_identitylink 参与者信息
* act_hi_procinst 流程实例
* act_hi_taskinst 任务实例
* act_ru_execution 执行表
* act_ru_identitylink 参与者信息
* act_ru_task 任务
*/
@Test
public void startProcessInstance() {
RuntimeService runtimeService = processEngine.getRuntimeService();
//启动流程实例
ProcessInstance processInstance = runtimeService
.startProcessInstanceByKey("myProcess_1");//这里的key就是流程图的ID
log.info("流程定义ID:" + processInstance.getProcessDefinitionId());
log.info("流程实例ID:" + processInstance.getId());
}
任务查询
流程启动后,各各任务的负责人就可以查询自己当前需要处理的任务,查询出来的任务都是该用户的待办任务。
/**
* 3
* 查询当前用户的任务列表
*/
@Test
public void findPersonalTaskList() {
TaskService taskService = processEngine.getTaskService();
//流程启动后,各各任务的负责人就可以查询自己当前需要处理的任务,查询出来的任务都是该用户的待办任务。
//根据流程定义的key,负责人assignee来实现当前用户的任务列表查询
List<Task> taskList = taskService.createTaskQuery()
//流程实例key
.processDefinitionKey("myProcess_1")
//查询谁的任务
.taskAssignee("张三")
.list();
for (Task task : taskList) {
System.out.println("-----------------------");
System.out.println("流程实例ID:" + task.getProcessInstanceId());
System.out.println("执行对象ID:" + task.getExecutionId ());
System.out.println("流程定义ID:" + task.getProcessDefinitionId ());
System.out.println("任务ID:" + task.getId());
System.out.println("任务名称:" + task.getName());
System.out.println("任务负责人:" + task.getAssignee());
System.out.println("任务的创建时间:" + task.getCreateTime ());
}
}
任务处理
任务负责人查询待办任务,选择任务进行处理,完成任务。
/**
* 3
* 处理当前用户的任务
* 背后操作的表:
* act_hi_actinst
* act_hi_identitylink
* act_hi_taskinst
* act_ru_identitylink
* act_ru_task
*/
@Test
public void completeTask() {
String processDefinitionKey = "myProcess_1";
TaskService taskService = processEngine.getTaskService();
//查询任务
Task task = taskService
.createTaskQuery()
.processDefinitionKey(processDefinitionKey)
.taskAssignee("张三")
.singleResult();
if(task != null){
//处理任务,结合当前用户任务列表的查询操作的话
taskService.complete(task.getId());
log.info("处理完成当前用户的任务");
}else{
log.info("当前用户暂无任务");
}
}
查询历史
/*
* 查询历史
* @author zq
* @param *[]
* @return void
**/
@Test
public void queryHistory() {
HistoryService historyService = processEngine.getHistoryService();
RepositoryService repositoryService = processEngine.getRepositoryService();
//查询流程定义
ProcessDefinitionQuery processDefinitionQuery =
repositoryService.createProcessDefinitionQuery();
String processDefinitionKey = "myProcess_1";
//遍历查询结果
ProcessDefinition processDefinition =
processDefinitionQuery
.processDefinitionKey(processDefinitionKey)
.orderByProcessDefinitionVersion().desc().singleResult();
if (processDefinition != null) {
HistoricActivityInstanceQuery query = historyService
.createHistoricActivityInstanceQuery();
List<HistoricActivityInstance> list =
query.processDefinitionId(processDefinition.getId())
.orderByHistoricActivityInstanceStartTime().asc().list();//排序StartTime
for (HistoricActivityInstance ai : list) {
System.out.println("历史活动ID:" + ai.getActivityId());
System.out.println("历史活动Name:" + ai.getActivityName());
System.out.println("流程定义ID" + ai.getProcessDefinitionId());
System.out.println("流程实例ID" + ai.getProcessInstanceId());
System.out.println("==============================");
}
}
}
执行结果