activiti工作流入门
什么是工作流?
工作流(Workflow),就是通过计算机对业务流程自动化执行管理。它主要解决的是“使在多个参与者之间按照某种预定义的规则自动进行传递文档、信息或任务的过程,从而实现某个预期的业务目标,或者促使此目标的实现”。通俗来讲,就是业务上一个完整的审批流程。例如员工的请假,出差,外出采购,合同审核等等,这些过程,都是一个工作流。
工作流引擎

常见的工作流引擎
主流的框架有:Activiti、jBPM、Camunda 、Flowable 、还有国产的盘古BPM、云程
activiti的使用
使用流程
-
引入依赖并初始化数据库
既然activiti是一个框架,那么我们肯定是需要引入对应的jar包 -
通过工具绘画流程图
使用 activiti 流程建模工具(activity-designer)定义业务流程(.bpmn 文件)
.bpmn 文件就是业务流程定义文件,通过 xml 定义业务流程。 -
流程定义部署;
向 activiti 部署业务流程定义(.bpmn 文件),使用 activiti 提供的 api 向 activiti 中部署.bpmn 文件,
通俗来讲,就是让activiti认识要使用的流程 -
启动一个流程实例(ProcessInstance)
启动一个流程实例表示开始一次业务流程的运行,比如员工请假流程部署完成,如果张三要请假就可以启动一个流程实例,如果李四要请假也启动一个流程实例,两个流程的执行互相不影响,就好比定义一个java类,实例化两个对象一样,部署的流程就好比java类,启动一个流程实例就好比new一个java对象 -
用户查询待办任务(Task)
因为现在系统的业务流程已经交给 activiti 管理,通过 activiti 就可以查询当前流程执行到哪了,当前用户需要办理什么任务了,这些 activiti帮我们管理了。实际上我们学习activiti也只是学习它的API怎么使用,因为很多功能activiti都已经封装好了,我们会调用就行了 -
用户办理任务
用户查询待办任务后,就可以办理某个任务,如果这个任务办理完成还需要其它用户办理,比如请假单创建后由部门经理审核,这个过程也是由 activiti 帮我们完成了,不需要我们在代码中硬编码指定下一个任务办理人了 -
流程结束
当任务办理完成没有下一个任务节点了,这个流程实例就完成了。
引入依赖
<!--引入activiti的springboot启动器 -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter</artifactId>
<version>7.1.0.M6</version>
<exclusions>
<exclusion>
<artifactId>mybatis</artifactId>
<groupId>org.mybatis</groupId>
</exclusion>
</exclusions>
</dependency>
添加配置
spring:
activiti:
# false:默认,数据库表不变,但是如果版本不对或者缺失表会抛出异常(生产使用)
# true:表不存在,自动创建(开发使用)
# create_drop: 启动时创建,关闭时删除表(测试使用)
# drop_create: 启动时删除表,在创建表 (不需要手动关闭引擎)
database-schema-update: true
#监测历史表是否存在,activities7默认不开启历史表
db-history-used: true
#none:不保存任何历史数据,流程中这是最高效的
#activity:只保存流程实例和流程行为
#audit:除了activity,还保存全部的流程任务以及其属性,audit为history默认值
#full:除了audit、还保存其他全部流程相关的细节数据,包括一些流程参数
history-level: full
#校验流程文件,默认校验resources下的process 文件夹的流程文件
check-process-definitions: true
数据库连接的url添加nullCatalogMeansCurrent=true
url: jdbc:mysql://localhost:3306/guigu-oa?serverTimezone=GMT%2B8&useSSL=false&characterEncoding=utf-8&nullCatalogMeansCurrent=true
通过工具绘画流程图
使用idea插件Activiti BPMN visualizer
流程定义部署
将资源文件放入rescource中
部署方式:单个部署、压缩包部署
@RunWith(SpringRunner.class)
@SpringBootTest
public class ProcessTest {
@Autowired
private RepositoryService repositoryService;
@Test
public void deployProcess() {
// 流程部署
Deployment deploy = repositoryService.createDeployment()
.addClasspathResource("process/qingjia.bpmn20.xml")
.addClasspathResource("process/qingjia.png")
.name("请假申请流程")
.deploy();
System.out.println(deploy.getId());
System.out.println(deploy.getName());
}
}
@Test
public void deployProcessByZip() {
// 定义zip输入流
InputStream inputStream = this
.getClass()
.getClassLoader()
.getResourceAsStream(
"process/qingjia.zip");
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
// 流程部署
Deployment deployment = repositoryService.createDeployment()
.addZipInputStream(zipInputStream)
.name("请假申请流程")
.deploy();
System.out.println("流程部署id:" + deployment.getId());
System.out.println("流程部署名称:" + deployment.getName());
}
启动流程实例
流程定义:将bpmn文件放到activiti的三张表中,好比是java中的一个类
流程实例:好比是java中的一个实例对象(一个流程定义可以对应多个流程实例),张三可以启动一个请假流程实例,李四也可以启动一个请假流程实例,他们互不影响
@Autowired
private RuntimeService runtimeService;
@Test
public void startUpProcess() {
//创建流程实例,我们需要知道流程定义的key
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("qingjia");
//输出实例的相关信息
System.out.println("流程定义id:" + processInstance.getProcessDefinitionId());
System.out.println("流程实例id:" + processInstance.getId());
System.out.println("当前活动Id:" + processInstance.getActivityId());
}
查询任务
每个节点都配置了Assignee,流程启动后,任务的负责人就可以查询自己当前需要处理的任务,查询出来的任务都是该用户的待办任务。
@Autowired
private TaskService taskService;
/**
* 查询当前个人待执行的任务
*/
@Test
public void findPendingTaskList() {
//任务负责人
String assignee = "zhangsan";
List<Task> list = taskService.createTaskQuery()
.taskAssignee(assignee)//只查询该任务负责人的任务
.list();
for (Task task : list) {
System.out.println("流程实例id:" + task.getProcessInstanceId());
System.out.println("任务id:" + task.getId());
System.out.println("任务负责人:" + task.getAssignee());
System.out.println("任务名称:" + task.getName());
}
}
说明:
流程实例id:一个流程只有一个,标识这个流程
任务id:流程每进行到某个节点,就会给这个节点分配一个任务id
输出结果如下:
流程实例id:d969f534-825e-11ed-95b4-7c57581a7819
任务id:d96c3f28-825e-11ed-95b4-7c57581a7819
任务负责人:zhangsan
任务名称:张三审批
处理当前任务
任务负责人查询待办任务,选择任务进行处理,完成任务。
完成任务后,任务自动到下一个节点
@Test
public void completeTask(){
Task task = taskService.createTaskQuery()
.taskAssignee("zhangsan")
.singleResult();//返回一条任务
taskService.complete(task.getId());
}
查询已处理的任务
@Autowired
private HistoryService historyService;
/**
* 查询已处理历史任务
*/
@Test
public void findProcessedTaskList() {
//张三已处理过的历史任务
List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery().taskAssignee("zhangsan").finished().list();
for (HistoricTaskInstance historicTaskInstance : list) {
System.out.println("流程实例id:" + historicTaskInstance.getProcessInstanceId());
System.out.println("任务id:" + historicTaskInstance.getId());
System.out.println("任务负责人:" + historicTaskInstance.getAssignee());
System.out.println("任务名称:" + historicTaskInstance.getName());
}
}
其他接口
/**
* 查询流程定义
*/
@Test
public void findProcessDefinitionList(){
List<ProcessDefinition> definitionList = repositoryService.createProcessDefinitionQuery()
.orderByProcessDefinitionVersion()
.desc()
.list();
//输出流程定义信息
for (ProcessDefinition processDefinition : definitionList) {
System.out.println("流程定义 id="+processDefinition.getId());
System.out.println("流程定义 name="+processDefinition.getName());
System.out.println("流程定义 key="+processDefinition.getKey());
System.out.println("流程定义 Version="+processDefinition.getVersion());
System.out.println("流程部署ID ="+processDefinition.getDeploymentId());
}
}
/**
* 删除流程定义
*/
public void deleteDeployment() {
//部署id
String deploymentId = "82e3bc6b-81da-11ed-8e03-7c57581a7819";
//删除流程定义,如果该流程定义已有流程实例启动则删除时出错
repositoryService.deleteDeployment(deploymentId);
//设置true 级联删除流程定义,即使该流程有流程实例启动也可以删除,设置为false非级别删除方式
//repositoryService.deleteDeployment(deploymentId, true);
}
浙公网安备 33010602011771号