1、关于Activiti
初学activiti我关心的它是什么东西、有什么功能、怎么实现?
先来看一张流程图感受一下:
activiti是一个业务流程管理引擎,它的流程图大概就像是列车的轨道,而所要执行的对象像是一辆自动运行的列车,只要列车启动,它就能沿着轨道一直走到终点,而其中的节点就像是列车到达终点途中所要经过的火车站,它会告诉火车下一站是哪里,然后火车就往指定的下一站驶去,直到终点,流程结束。
如上所描述,最主要的功能就是实现了代码的自动按流程执行
关于怎么实现,既然这是一个框架,自然就是引进jar包,画流程图,然后实现该框架提供的接口来做我们想要做的事情。
2、Activiti数据库的理解
activiti在每个节点都能知道下一个节点是什么,以及当前任务是什么,那势必会有存储流程的各种信息的表。事实也确实如此,activiti可以配置数据库,其中存储了流程运行时的相关信息。在初学Activiti之时,了解activiti所有的数据库表的含义对理解activiti工作机制是有很大帮助的,activiti总共涉及的表格总共有23个:
act_ge_*:general通用数据,用于存放数据。
act_re_*:reposity类似于仓库,存放流程定义文件和流程图片文件,比如一个流程部署之后可以在act_re_deployment表中看到。
act_ru_*:run服务运行时候的数据,当一个流程启动之后当前的活动任务可以在act_ru_task表格中查看 ,以及流程中所有的变量都保存在act_ru_variable表格当中。
本来想写一系列完整的Activiti的学习笔记的,但是学完之后发现工作量着实不小,自身学的也不够深,况且网上大有牛人有类似的学习笔记,所以此文权当是个人学习activiti的过程中填坑记录,仅供参考;
3、运行环境搭建,最简单的运行环境(学习中用到了Junit 4用来测试很好用。),eclipse+jar包+mysql,配置文件,因为我这里没有与Spring整合,所以配置文件就一个activiti.cfg.xml放在class_path下面就好了。
4、下载画流程工具activiti-app.war
从官网下载war包(登录用户密码:admin test),找到activiti-app.war放进tomcat,启动之后自己画一个流程图,用于下面的测试
war包下载:https://www.activiti.org/down...
版本6.xx的相关文档都在这里:https://www.activiti.org/docs
版本5.xx的官网好像不再维护了
[画图工具]
5、开始实现Activiti的一些api,并查看表格中的变化
package com.lewin.activiti.taskListener;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.TaskService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.apache.commons.io.FileUtils;
import org.junit.Test;
public class DepolyTest {
@Test
public void run(){
//获取流程引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
Deployment deployment = processEngine.getRepositoryService()
.createDeployment()
//.addClasspathResource("taskListener.bpmn20.xml")
.addClasspathResource("UserExecuteTask.bpmn20.xml")
.deploy();
String piid = deployment.getId();
System.out.println("processDefinitionId:"+piid);
//String processKey = "lewin";
String processKey = "UserExecuteTask";
ProcessInstance pi = processEngine.getRuntimeService().startProcessInstanceByKey(processKey);
System.out.println(pi.getId());
}
/**
* 根据流程定义里的id启动流程实例
*/
public void startInstance(){
String processInstanceKey = "lewin";
//“lewin”即对应着流程定义中的id值
ProcessInstance pi = ProcessEngines.getDefaultProcessEngine()
.getRuntimeService()
.startProcessInstanceByKey(processInstanceKey);
System.out.println("started processInstance id is:"+processInstanceKey+"; pi.id is:"+pi.getId());
}
/*
* 从class_path中部署流程实例
*/
@Test
public void deploymentProcessDefinition_classpath(){
//获取流程引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
Deployment deployment = processEngine.getRepositoryService()//获取仓库服务
.createDeployment()//创建部署实例
.name("deploymentName")//设置将要部署的流程实例的名称
.addClasspathResource("taskListener.bpmn20.xml")//资源文件:默认路径在class_path下面
//.addClasspathResource("diagrams/HelloWorld.png")
.deploy();//部署
System.out.println("id:"+deployment.getId());
System.out.println("name:"+deployment.getName());
}
/*
* 查询定义了的流程
* 查询内容来自act_re_deployment
*/
@Test
public void findProcessDefinition(){
//获取流程引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
List list = processEngine.getRepositoryService()
.createProcessDefinitionQuery()
//.deploymentId(deploymentId)
//.processDefinitionId(processDefinitionId)
//.processDefinitionKey(processDefinitionKey)
//.processDefinitionNameLike(processDefinitionNameLike)
.orderByProcessDefinitionVersion().asc()
//.orderByProcessDefinitionName().desc()
.list();
//.singleResult();
//.count();
//.listPage(firstResult, maxResults)
if(list != null && list.size()>0){
for(ProcessDefinition processDefinition:list){
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("resourceName:"+processDefinition.getResourceName());
System.out.println("图片名字:"+processDefinition.getDiagramResourceName());
System.out.println("部署的流程id:"+processDefinition.getDeploymentId());
System.out.println("################################");
}
}
}
/*
* 删除流程定义
*/
@Test
public void deleteProcessDefinition(){
//获取流程引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//流程定义id
String deploymentId = "2201";
processEngine.getRepositoryService()
.deleteDeployment(deploymentId, true);
System.out.println("删除成功!");
}
/*
* 查看流程定义图并下载到本地
*/
@Test
public void viewPic() throws IOException{
//获取流程引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
/**流程部署id*/
String deploymentId = "201";
//根据id获取存储在act_re_deployment表里面的静态资源,里面就有图片
List list = processEngine.getRepositoryService()//
.getDeploymentResourceNames(deploymentId);
//获取名字
String resourceName = "";
if(list!=null && list.size()>0){
for(String name:list){
if(name.indexOf(".png")>=0){
resourceName = name;
}
}
}
//获取图片资源
InputStream in = processEngine.getRepositoryService()//
.getResourceAsStream(deploymentId, resourceName);
//新建文件
File file = new File("D:/"+resourceName);
//文件复制
FileUtils.copyInputStreamToFile(in, file);
}
/*
* 删除路程定义根据定义中的名字
*/
@Test
public void deleteProcessDefinitionByKey(){
//获取流程引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//流程定义文件中的名字,如果相同名字有多个默认使用版本最高的那个
String processDefinitionKey = "UserExecuteTask";
List list = processEngine.getRepositoryService()
.createProcessDefinitionQuery()
.processDefinitionKey(processDefinitionKey)
.list();
//删除所有名字为UserExecuteTask的流程定义
if(list!=null && list.size()>0){
for(ProcessDefinition pd:list){
//获取ID
String deploymentId = pd.getDeploymentId();
processEngine.getRepositoryService()
.deleteDeployment(deploymentId);
}
}
}
/**
* 查询流程状态
*/
@Test
public void queryInstanceState(){
//流程id
String instanceId = "1309";
//任务id
String taskId = "1312";
//获取流程引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//通过流程id查询状态
ProcessInstance pi = processEngine.getRuntimeService()
.createProcessInstanceQuery()//创建查询
.processInstanceId(instanceId)//根据id
.singleResult();//获取状态
if(pi!=null){
System.out.println("id为"+instanceId+"的流程正在进行中......");
//完成当前节点
processEngine.getTaskService().complete(taskId);
}else{
System.out.println("id为"+instanceId+"的流程已经完成!");
}
}
/**
* 查询流程执行对象
*/
@Test
public void queryExecution(){
//查询执行对象
String exe = "User Task";
//获取流程实例
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//查询
Execution e1 = processEngine.getRuntimeService()
.createExecutionQuery()
.processInstanceId("1509")
.activityId(exe)
.singleResult();
if(e1!=null){
System.out.println("e1!=null");
}else{
System.out.println("e1==null");
}
}
/**
* 根据用户查询任务
*/
@Test
public void queryUserTask(){
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// Fetch all tasks for the management group
TaskService taskService = processEngine.getTaskService();
List tasks = taskService.createTaskQuery().taskCandidateGroup("management").list();
for (Task task : tasks) {
System.out.println("Task available: " + task.getName());
}
}
}
6、例子1:只有用户任务和并行网关的运行
UserExecuteTask.bpmn20.xml文件:
测试代码:
/**
* 对应UserExecuteTask.bpmn20.xml
* 这是一个用户任务,所以流程完全执行需要用户的参与
* 获取所有任务
*
*/
@Test
public void getAllTasks(){
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取仓库实例
Deployment deployment = processEngine.getRepositoryService()
.createDeployment()
.addClasspathResource("UserExecuteTask.bpmn20.xml")
.deploy();
//启动流程实例
ProcessInstance pi = processEngine.getRuntimeService()
.startProcessInstanceByKey("UserExecuteTask");
System.out.println("pi.id:"+pi.getId());
//第一轮(流程启动之后自动进入下一级节点,
//下一级节点为并行的三个任务,获取该三个任务依次按定义文件中顺序完成)
TaskService taskService = processEngine.getTaskService();
TaskQuery query = taskService.createTaskQuery().processInstanceId(pi.getId()).orderByTaskName().asc();
List tasks = query.list();
//循环打印tasks的信息
for(Task task : tasks){
//执行任务 ,完成任务
taskService.complete(task.getId());
System.out.println("name ="+task.getName());
System.out.println(tasks.size());
}
//第二轮查询任务:上一轮三个任务依次完成之后开始进入下一轮,第二级节点
tasks = query.list();
//循环打印tasks的信息
for(Task task : tasks){
//执行任务 ,完成任务
taskService.complete(task.getId());
System.out.println("name ="+task.getName());
System.out.println(tasks.size());
}
//第三轮查询任务:上一轮一个任务完成之后,开始进入下一级节点,
//即最后的人事部门审批
tasks = query.list();
//循环打印tasks的信息
for(Task task : tasks){
//执行任务 ,完成任务
taskService.complete(task.getId());
System.out.println("name ="+task.getName());
System.out.println(tasks.size());
}
}
运行结果:
7、例子2:只有系统任务和并行网关的运行
AutoUserExecuteTask.bpmn20.xml文件:
测试代码:
/**
* 对应UserExecuteTask.bpmn20.xml
* 这是一个自动任务(不包含用户任务),所以流程完全执行不需要用户的参与
* 只需要启动实例,流程会自动按流程走完
* 获取所有任务
*
*/
@Test
public void autoRun(){
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取仓库实例
Deployment deployment = processEngine.getRepositoryService()
.createDeployment()
.addClasspathResource("AutoUserExecuteTask.bpmn20.xml")
.deploy();
//启动流程实例
ProcessInstance pi = processEngine.getRuntimeService()
.startProcessInstanceByKey("AutoUserExecuteTask");
System.out.println("pi.id:"+pi.getId());
}
运行结果:
![图片上传中...]
8、例子3:只有用户任务和排他网关的运行
ExclusiveGatawayDemo.bpmn20.xml文件:
ExclusiveGatawayDemo
测试代码:
/**
* 对应ExclusiveGatewayDemo.bpmn20.xml
* 包含排他网关的流程
* 获取所有任务
*
*/
@Test
public void exclusiveGatewayTasks(){
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取仓库实例
Deployment deployment = processEngine.getRepositoryService()
.createDeployment()
.name("ExclusiveGatawayDemo_Deploymentname")
.addClasspathResource("ExclusiveGatawayDemo.bpmn20.xml")
.deploy();
//启动流程实例
ProcessInstance pi = processEngine.getRuntimeService()
.startProcessInstanceByKey("ExclusiveGatawayDemo");
System.out.println("pi.id:"+pi.getId());
//第一轮(流程启动之后自动进入下一级节点,
//下一级节点为并行的三个任务,获取该三个任务依次按定义文件中顺序完成)
TaskService taskService = processEngine.getTaskService();
TaskQuery query = taskService.createTaskQuery().processInstanceId(pi.getId()).orderByTaskName().asc();
List tasks = query.list();
//循环打印tasks的信息
for(Task task : tasks){
//执行任务 ,完成任务
taskService.complete(task.getId());
System.out.println("name ="+task.getName());
System.out.println(tasks.size());
}
/**
* userTask1完成,并且设置变量“myCondition”
* 这里测试设置的值是"userTask3"
* 按照定义应该执行userTask3
* 注释下面代码的情况下,查询act_ru_task可以查看到有userTask3任务
* 不注释的情况下,流程完成userTask1和userTask3走完整个流程
*/
//第二轮查询任务:上一轮三个任务依次完成之后开始进入下一轮,第二级节点
tasks = query.list();
//循环打印tasks的信息
for(Task task : tasks){
//执行任务 ,完成任务
taskService.complete(task.getId());
System.out.println("name ="+task.getName());
System.out.println(tasks.size());
}
//第三轮查询任务:上一轮一个任务完成之后,开始进入下一级节点,
//即最后的人事部门审批
tasks = query.list();
//循环打印tasks的信息
for(Task task : tasks){
//执行任务 ,完成任务
taskService.complete(task.getId());
System.out.println("name ="+task.getName());
System.out.println(tasks.size());
}
}
运行结果:
字数不够,代码来凑,草草结束,细节之处多有遗漏,有一起学习的有问题的可以私信。强行回顾了一下前两天的学习历程。