Activiti7工作流学习笔记一
工作流(Workflow),就是“业务过程的部分或整体在计算机应用环境下的自动化”,它主要解决的是“使在多个参与者之间按照某种预定义的规则传递文档、信息或任务的过程自动进行,从而实现某个预期的业务目标,或者促使此目标的实现”。
工作流管理系统(Workflow Management System, WfMS)是一个软件系统,它完成工作量的定义和管理,并按照在系统中预先定义好的工作流规则进行工作流实例的执行。工作流管理系统不是企业的业务系统,而是为企业的业务系统的运行提供了一个软件的支撑环境。
工作流管理联盟(WfMC,Workflow Management Coalition)给出的关于工作流管理系统的定义是:工作流管理系统是一个软件系统,它通过执行经过计算的流程定义去支持一批专门设定的业务流程。工作流管理系统被用来定义、管理、和执行工作流程。
工作流管理系统的目标:管理工作的流程以确保工作在正确的时间被期望的人员所执行——在自动化进行的业务过程中插入人工的执行和干预。
Activiti原理分析
使用方式
- 定义工作流
使用eclipse插件完成,leaveProcess.bpmn(计算机进行流程的执行与信息的传递使用);leaveProcess.png用户使用,查看流程的进度
使用https://demo.bpmn.io/,官方推荐 - 执行和管理工作流
调用Activiti的API
1. 流程部署
- 创建
processEngine
对象 - 得到
repositoryService
实例 - 进行部署
- 输出部署的一些信息
表说明
表名 | 作用 |
---|---|
act_re_deployment | 流程定义部署表,记录流程部署信息 |
act_re_procdef | 流程定义表,记录流程定义信息 |
act_ge_bytearray | 资源表 |
说明:
act_re_deployment
和 act_re_procdef
一对多关系
- 一次部署在流程部署表生成一条记录,但一次部署可以部署多个流程定义
- 每个流程定义在流程定义表生成一条记录
- 每一个流程定义在
act_ge_bytearray
会存在两个资源记录,bpmn
和png
。
建议:一次部署一个流程,这样部署表和流程定义表是一对一有关系,方便读取流程部署及流程定义信息。
/**
* com.lxf.activiti
* 流程定义的部署
* act_re_deployment 部署信息
* act_re_procdef 流程定义的一些信息
* act_ge_bytearray 流程定义的bpmn文件及png文件
* @author lxf
* @version 1.0
* @date 2020/4/23 21:20
*/
public class ActivitiDeployment {
// 流程定义部署
public static void main(String[] args) {
// 1.创建processEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 2.得到repositoryService实例
RepositoryService repositoryService = processEngine.getRepositoryService();
// 3.进行部署
DeploymentBuilder deploymentBuilder = repositoryService.createDeployment()
.addClasspathResource("diagrams/holiday1.bpmn")
.addClasspathResource("diagrams/holiday.png")
.name("请假流程申请单");
Deployment deployment = deploymentBuilder.deploy();
// 4.输出部署的一些信息
System.out.println(deployment.getName());
System.out.println(deployment.getId());
}
/**
* 压缩形式部署
* 把bpmn,png文件制成zip类型的压缩包
*/
public void deploymentZip(){
//1.创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到RepositoryService实例
RepositoryService repositoryService = processEngine.getRepositoryService();
//3.转化出ZipInputStream流对象
InputStream is = ActivitiDeployment.class.getClassLoader().getResourceAsStream("diagrams/holidayBPMN.zip");
//将 inputstream流转化为ZipInputStream流
ZipInputStream zipInputStream = new ZipInputStream(is);
//3.进行部署
Deployment deployment = repositoryService.createDeployment()
.addZipInputStream(zipInputStream)
.name("请假申请单流程")
.deploy();
//4.输出部署的一些信息
System.out.println(deployment.getName());
System.out.println(deployment.getId());
}
}
2. 启动流程实例
- 流程定义
bpmn文件
- 流程部署
activiti的三张表
- 流程实例
流程定义类似Java中的一个类
流程实例类似 Java中的一个实例(对象),一个流程定义可以对应多个流程实例
表说明
表名 | 作用 |
---|---|
act_hi_actinst | 已完成的活动信息 |
act_hi_identitylink | 参与者信息 |
act_hi_procinst | 流程实例 |
act_hi_taskinst | 任务实例 |
act_ru_execution | 执行表 |
act_ru_identitylink | 参与者信息 |
act_ru_task | 任务 |
/**
* 启动流程实例:
* 前提是先已经完成流程定义的部署工作
*
* 背后影响的表:
* act_hi_actinst 已完成的活动信息
* act_hi_identitylink 参与者信息
* act_hi_procinst 流程实例
* act_hi_taskinst 任务实例
* act_ru_execution 执行表
* act_ru_identitylink 参与者信息
* act_ru_task 任务
*/
public class ActivitiStartInstance {
public static void main(String[] args) {
//1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到RunService对象
RuntimeService runtimeService = processEngine.getRuntimeService();
//3.创建流程实例 流程定义的key需要知道 holiday
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holiday");
//4.输出实例的相关信息
//null
System.out.println("流程部署ID->" + processInstance.getDeploymentId());
//holiday:1:5004
System.out.println("流程定义ID->" + processInstance.getProcessDefinitionId());
//10001
System.out.println("流程实例ID->" + processInstance.getId());
//null
System.out.println("活动ID->" + processInstance.getActivityId());
}
}
流程部署ID->null
流程定义ID->holiday:1:5004
流程实例ID->10001
活动ID->null
3. 查询任务列表
/**
* 查询当前用户的任务列表
*/
public class ActivitiTaskQuery {
public static void main(String[] args) {
ActivitiTaskQuery taskQuery = new ActivitiTaskQuery();
taskQuery.taskQuery4ZhangSan();
}
/**
* wangwu完成自己任务列表的查询
*/
public void taskQuery4WangWu() {
//1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到TaskService对象
TaskService taskService = processEngine.getTaskService();
//3.根据流程定义的key,负责人assignee来实现当前用户的任务列表查询
Task task = taskService.createTaskQuery()
.processDefinitionKey("holiday")
.taskAssignee("wangwu")
.singleResult();
//4.任务列表的展示
printTaskInfo(task);
}
/**
* lishi完成自己任务列表的查询
*/
public void taskQuery4LiShi() {
//1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到TaskService对象
TaskService taskService = processEngine.getTaskService();
//3.根据流程定义的key,负责人assignee来实现当前用户的任务列表查询
Task task = taskService.createTaskQuery()
.processDefinitionKey("holiday")
.taskAssignee("lishi")
.singleResult();
//4.任务列表的展示
printTaskInfo(task);
}
/**
* zhangsan任务列表的查询
*/
public void taskQuery4ZhangSan() {
//1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到TaskService对象
TaskService taskService = processEngine.getTaskService();
//3.根据流程定义的key,负责人assignee来实现当前用户的任务列表查询
List<Task> taskList = taskService.createTaskQuery()
.processDefinitionKey("holiday")
.taskAssignee("zhangsan")
.list();
//4.任务列表的展示
taskList.stream().forEach(this::printTaskInfo);
}
/**
* 输出任务信息
*/
public void printTaskInfo(Task task) {
System.out.println("流程实例ID:" + task.getProcessInstanceId());
System.out.println("任务ID:" + task.getId());
System.out.println("任务负责人:" + task.getAssignee());
System.out.println("任务名称:" + task.getName());
}
}
结果:
流程实例ID:10001
任务ID:10005
任务负责人:zhangsan
任务名称:填写请假申请单
流程实例ID:7501
任务ID:7505
任务负责人:zhangsan
任务名称:填写请假申请单
4. 处理当前用户的任务
/**
* 处理当前用户的任务 背后操作的表:
* act_hi_actinst
* act_hi_identitylink 记录参与者
* act_hi_taskinst
* act_ru_identitylink
* act_ru_task 当前正要执行的任务,每次从流程图中载入一个任务,当任务完成后删除,最终为空
*/
public class ActivitiCompleteTask {
public static void main(String[] args) {
ActivitiCompleteTask completeTask = new ActivitiCompleteTask();
completeTask.zhangSanComplete();
completeTask.complete("lishi");
completeTask.complete("wangwu");
}
/**
* zhangsan完成自己的任务
*/
public void zhangSanComplete() {
//1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到TaskService对象
TaskService taskService = processEngine.getTaskService();
//3.处理任务,结合当前用户任务列表的查询操作的话,任务ID:10005
taskService.complete("10005");
}
/**
* 查询当前用户的任务并处理掉
*/
public void complete(String assignee) {
//1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到TaskService对象
TaskService taskService = processEngine.getTaskService();
//3.查询当前用户的任务
List<Task> taskList = taskService.createTaskQuery()
.processDefinitionKey("holiday")
.taskAssignee(assignee)
.list();
taskList.stream().forEach(task -> {
//4.处理任务,结合当前用户任务列表的查询操作的话,任务ID:task.getId()
taskService.complete(task.getId());
//5.输出任务的id
System.out.println(task.getId());
});
}
}
流程定义
查看流程定义信息
/**
* 操作一、查询流程定义信息
*/
public void queryProcessDefinition() {
//1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.创建RepositoryService对象
RepositoryService repositoryService = processEngine.getRepositoryService();
//3.得到ProcessDefinitionQuery对象,可以认为它就是一个查询器
ProcessDefinitionQuery processDefinitionQuery = repositoryService
.createProcessDefinitionQuery();
//4.设置条件,并查询出当前的所有流程定义 查询条件:流程定义的key=holiday
//orderByProcessDefinitionVersion() 设置排序方式,根据流程定义的版本号进行排序
List<ProcessDefinition> list = processDefinitionQuery.processDefinitionKey("holiday")
.orderByProcessDefinitionVersion()
.desc().list();
//5.输出流程定义信息
list.forEach(this::printProcessDefinitionInfo);
}
/**
* 输出流程定义信息
*/
public void printProcessDefinitionInfo(ProcessDefinition processDefinition) {
System.out.println("流程定义ID:" + processDefinition.getId());
System.out.println("流程定义名称:" + processDefinition.getName());
System.out.println("流程定义的Key:" + processDefinition.getKey());
System.out.println("流程定义的版本号:" + processDefinition.getVersion());
System.out.println("流程部署的ID:" + processDefinition.getDeploymentId());
}
输出
流程定义ID:holiday:1:5004
流程定义名称:请假流程
流程定义的Key:holiday
流程定义的版本号:1
流程部署的ID:5001
删除流程定义信息
/**
* 删除流程定义信息
* 背后影响的表(与流程部署用到的一致):
* act_ge_bytearray
* act_re_deployment
* act_re_procdef
* 注意事项:
* 1.当我们正在执行的这一套流程没有完全审批结束的时候,此时如果要删除流程定义信息就会失败
* 2.如果公司层面要强制删除,可以使用repositoryService.deleteDeployment("1",true);
* 参数true代表级联删除,此时就会先删除没有完成的流程结点,最后就可以删除流程定义信息
* false的值代表不级联
* @param repositoryService
* @param deployId
*/
public void deleteDeployment(RepositoryService repositoryService,String deployId){
//6.执行删除流程定义 参数代表流程部署的id
repositoryService.deleteDeployment(deployId);
}
流程定义资源查询
需求:
- 从
Activiti
的act_ge_bytearray
表中读取两个资源文件 - 将两个资源文件保存到路径:
d:\resources
技术方案:
1.第一种方式使用actviti的api来实现
2.第二种方式:其实就是原理层面,可以使用jdbc的对blob类型,clob类型数据的读取,并保存
IO流转换,最好commons-io.jar包可以轻松解决IO操作
真实应用场景:用户想查看这个请假流程具体有哪些步骤要走?
public void queryBpmnFile() throws IOException {
//1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到RepositoryService对象
RepositoryService repositoryService = processEngine.getRepositoryService();
//3.得到查询器:ProcessDefinitionQuery对象
ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
//4.设置查询条件
processDefinitionQuery.processDefinitionKey("holiday");//参数是流程定义的key
//5.执行查询操作,查询出想要的流程定义
ProcessDefinition processDefinition = processDefinitionQuery.singleResult();
//6.通过流程定义信息,得到部署ID
String deploymentId = processDefinition.getDeploymentId();
//7.通过repositoryService的方法,实现读取图片信息及bpmn文件信息(输入流)
//getResourceAsStream()方法的参数说明:第一个参数部署id,第二个参数代表资源名称
//processDefinition.getDiagramResourceName() 代表获取png图片资源的名称
//processDefinition.getResourceName()代表获取bpmn文件的名称
InputStream pngIs = repositoryService
.getResourceAsStream(deploymentId,processDefinition.getDiagramResourceName());
InputStream bpmnIs = repositoryService
.getResourceAsStream(deploymentId,processDefinition.getResourceName());
//8.构建出OutputStream流
OutputStream pngOs =
new FileOutputStream("G:\\Activiti7开发计划\\Activiti7-day03\\资料\\"+processDefinition.getDiagramResourceName());
OutputStream bpmnOs =
new FileOutputStream("G:\\Activiti7开发计划\\Activiti7-day03\\资料\\"+processDefinition.getResourceName());
//9.输入流,输出流的转换 commons-io-xx.jar中的方法
IOUtils.copy(pngIs,pngOs);
IOUtils.copy(bpmnIs,bpmnOs);
//10.关闭流
pngOs.close();
bpmnOs.close();
pngIs.close();
bpmnIs.close();
}
历史数据的查看
/**
* com.lxf.activiti.ProcessDefinition
* 历史数据的查看
* @author lxf
* @version 1.0
* @date 2020/4/25 19:30
*/
public class HistoryQuery {
public static void main(String[] args) throws IOException {
//1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到HistoryService
HistoryService historyService = processEngine.getHistoryService();
//3.得到HistoricActivitiInstanceQuery对象
HistoricActivityInstanceQuery historicActivityInstanceQuery = historyService.createHistoricActivityInstanceQuery();
//设置流程实例的id
historicActivityInstanceQuery.processInstanceId("2501");
//4.执行查询
List<HistoricActivityInstance> list = historicActivityInstanceQuery
//排序StartTime
.orderByHistoricActivityInstanceStartTime().asc().list();
//5.遍历查询结果
list.forEach(instance->{
System.out.println(instance.getActivityId());
System.out.println(instance.getActivityName());
System.out.println(instance.getProcessDefinitionId());
System.out.println(instance.getProcessInstanceId());
System.out.println("=============================");
});
}
}
IDEA在快捷键
作用 | |
---|---|
Alt+ Insert |
IDEA maven项目pom文件插入依赖快捷键 |