工作流概述
工作流(Workflow),就是“业务过程的部分或整体在计算机应用环境下的自动化”,它主要解决的是“使在多个参与者之间按照某种预定义的规则传递文档、信息或任务的过程自动进行,从而实现某个预期的业务目标,或者促使此目标的实现”。
工作流Activity连接数据库(xml文件配置方法)
--activiti.cfg.xml
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<!-- 连接数据库的配置 -->
<property name="jdbcDriver" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/study?useUnicode=true&characterEncoding=utf8"></property>
<property name="jdbcUsername" value="root"></property>
<property name="jdbcPassword" value="123456"></property>
<!-- 没有表创建表 -->
<property name="databaseSchemaUpdate" value="true"></property>
</bean>
Activity工作流的23张数据库表
1) ACT_RE_*: 'RE'表示repository。 这个前缀的表包含了流程定义和流程静态资源 (图片,规则,等等)。
2) ACT_RU_*: 'RU'表示runtime。 这些运行时的表,包含流程实例,任务,变量,异步任务,等运行中的数据。 Activiti只在流程实例执行过程中保存这些数据, 在流程结束时就会删除这些记录。这样运行时表可以一直很小速度很快。
3) ACT_ID_*: 'ID'表示identity。 这些表包含身份信息,比如用户,组等等。
4) ACT_HI_*: 'HI'表示history。 这些表包含历史数据,比如历史流程实例, 变量,任务等等。
5) ACT_GE_*: 通用数据, 用于不同场景下。
Activity工作流的核心——ProcessEngine(工作流的引擎)
Activity工作流操作api
RepositoryService 管理流程定义(仓库)
RuntimeService 执行管理,包括启动、推进、删除流程实例等操作
TaskService 任务管理
Activity工作流的流程定义
package com.study.processdefinition;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.repository.Deployment;
import org.junit.Test;
import org.activiti.engine.repository.ProcessDefinition;
import org.apache.commons.io.FileUtils;
public class ProcessDefinitions {
ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();
/**
* 部署流程定义(从classpath)
*/
@Test
public void deploymentProcessDefinition_classpath() {
Deployment deployment =processEngine.getRepositoryService()
.createDeployment()
.name("流程定义")
.addClasspathResource("diagrams/helloworld.bpmn")
.addClasspathResource("diagrams/helloworld.png")
.deploy();
System.out.println("部署ID:"+deployment.getId());
System.out.println("部署名称:"+deployment.getName());
}
/**
* 部署流程定义(从zip)
*/
@Test
public void deploymentProcessDefinition_zip() {
InputStream in=this.getClass().getClassLoader().getResourceAsStream("helloworld.zip");
ZipInputStream zipin=new ZipInputStream(in);
Deployment deployment=processEngine.getRepositoryService()
.createDeployment()
.name("流程定义")
.addZipInputStream(zipin)
.deploy();
System.out.println("部署ID:"+deployment.getId());
System.out.println("部署名称:"+deployment.getName());
}
/**
* 查询流程定义
*/
@Test
public void findProcessDefinition() {
List<ProcessDefinition> list= processEngine.getRepositoryService()
.createProcessDefinitionQuery()
// .deploymentId(deploymentId)//使用部署对象ID查询
// .processDefinitionKey(processDefinitionKey)//使用流程定义ID查询
// .processDefinitionName(processDefinitionName)//使用流程定义的key查询
/**排序*/
.orderByProcessDefinitionCategory().asc()//按照版本的升序排列
// .orderByProcessDefinitionName().desc()//按照流程定义的名称降序排列
/**
* 返回的结果集
*/
.list();//返回一个集合列表,封装流程定义
// .singleResult();//返回唯一结果集
// .count();//返回结果集数量
// .listPage(firstResult, maxResults);//分页查询
if(list!=null && list.size()>0) {
for (ProcessDefinition pd : list) {
System.out.println("流程定义ID:"+pd.getId());
System.out.println("流程定义的名称:"+pd.getName());
System.out.println("流程定义的key:"+pd.getKey());
System.out.println("流程定义的版本:"+pd.getVersion());
System.out.println("资源名称bpmn文件:"+pd.getResourceName());
System.out.println("资源名称png文件:"+pd.getDiagramResourceName());
System.out.println("部署对象ID:"+pd.getDeploymentId());
System.out.println("###########################");
}
}
}
/**
* 删除流程定义
*/
@Test
public void deleteProcessDefinition() {
String deploymentId="";
/**
*不带级联的删除
* 只能删除没有启动的流程,如果流程启动,就会抛出异常
*/
processEngine.getRepositoryService()
.deleteDeployment(deploymentId);
/**
* 级联删除
* 不管流程是否启动,都可以删除
*/
processEngine.getRepositoryService()
.deleteDeployment(deploymentId,true);
System.out.println("删除成功!!");
}
/**
* 查看流程图
* @throws IOException
*/
@Test
public void viewPic() throws IOException {
/**
* 将生成图片写到文件夹下
*/
String deploymentId="12501";
//获取图片资源的名称
List<String> 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);
//将图片生成 到D盘的目录下
File file=new File("D:/"+resourceName);
//将输入流的图片写到D盘下
FileUtils.copyInputStreamToFile(in, file);
}
/**
* 查询最新版本的流程定义
*/
@Test
public void findLastVersionProcessDefinition() {
List<ProcessDefinition>list= processEngine.getRepositoryService()
.createProcessDefinitionQuery()
.orderByProcessDefinitionVersion().asc()
.list();
/**
* map<String,ProcessDefinition>
* map集合的key:流程定义的key
* map集合的value:流程定义的对象
* map集合的特点:当map集合key值相同的情况下,后一次的值将替换前一次的值
*/
Map<String, ProcessDefinition> map=new LinkedHashMap<String,ProcessDefinition>();
if(list!=null && list.size()>0) {
for (ProcessDefinition pd : list) {
map.put(pd.getKey(), pd);
}
}
List<ProcessDefinition> pdList=new ArrayList<ProcessDefinition>(map.values());
if(pdList !=null && pdList.size()>0) {
for (ProcessDefinition pd : pdList) {
System.out.println("流程定义ID:"+pd.getId());
System.out.println("流程定义的名称:"+pd.getName());
System.out.println("流程定义的key:"+pd.getKey());
System.out.println("流程定义的版本:"+pd.getVersion());
System.out.println("资源名称bpmn文件:"+pd.getResourceName());
System.out.println("资源名称png文件:"+pd.getDiagramResourceName());
System.out.println("部署对象ID:"+pd.getDeploymentId());
System.out.println("###########################");
}
}
}
/**
* 删除流程定义(删除key相同下不同版本的流程定义)
*/
@Test
public void deleteProcessDefinitionByKey() {
//流程定义的key
String key="";
//先使用流程定义的key查询流程定义,查询出所有的版本
List<ProcessDefinition> list=processEngine.getRepositoryService()
.createProcessDefinitionQuery()
.processDefinitionKey(key)
.list();
//遍历,获取每个流程定义的部署ID
if(list!=null && list.size()>0) {
for (ProcessDefinition pd : list) {
//获取部署ID
String deploymentId=pd.getDeploymentId();
processEngine.getRepositoryService()
.deleteDeployment(deploymentId,true);
}
}
}
}
流程定义不能被修改
流程定义相关的表
act_re_deployment 部署对象表
act_re_procdef 流程定义表
act_ge_bytearray 资源文件表
act_ge_property 主键生成策略表
Activity工作流执行任务
package com.study.activiti;
import java.util.List;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.junit.Test;
public class HelloWorld {
ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();
/**
* 部署流程定义
*/
@Test
public void deploymentProcessDefinition() {
Deployment deployment=processEngine.getRepositoryService() //与流程定义和部署对象相关的service
.createDeployment() //创建一个部署对象
.name("helloworld入门程序")//添加部署的名称
.addClasspathResource("diagrams/helloworld.bpmn")//从classpath的资源中加载,一次只能加载一个文件
.addClasspathResource("diagrams/helloworld.png")//从classpath的资源中加载,一次只能加载一个文件
.deploy();//完成部署
System.out.println("部署ID:"+deployment.getId());
System.out.println("部署名称:"+deployment.getName());//helloworld入门程序
}
/**
* 启动流程实例
*/
@Test
public void startProcessInstance() {
//流程定义的key
String processDefinitionKey="helloworldId";
ProcessInstance pi=processEngine.getRuntimeService()//与正在执行的流程实例和执行对象相关的Service
.startProcessInstanceByKey(processDefinitionKey);//使用流程定义的key启动流程实例,key对应helloworld.bpmn文件中id的属性值,使用key值启动,默认是按照最新版本的流程定义启动
System.out.println("流程实例ID:"+pi.getId());
System.out.println("流程定义ID:"+pi.getProcessDefinitionId());
}
/**
* 查询当前人的个人任务
*/
@Test
public void findMyPersonalTask() {
String assignee="王五";
List<Task> list=processEngine.getTaskService()//与正在执行的任务管理相关的Service
.createTaskQuery()//创建任务查询对象
.taskAssignee(assignee)//指定个人任务查询,指定办理人
.list();
if(list!=null && list.size()>0) {
for (Task task : list) {
System.out.println("任务ID:"+task.getId());
System.out.println("任务名称:"+task.getName());
System.out.println("任务的创建时间:"+task.getCreateTime());
System.out.println("任务的办理人:"+task.getAssignee());
System.out.println("流程实例ID:"+task.getProcessInstanceId());
System.out.println("执行对象ID:"+task.getExecutionId());
System.out.println("流程定义ID:"+task.getProcessDefinitionId());
System.out.println("####################################");
}
}
}
/**
* 完成我的任务
*/
@Test
public void completeMyPersonalTask() {
//任务ID
String taskId="7502";
processEngine.getTaskService()//与正在执行的任务管理相关的Service
.complete(taskId);
System.out.println("完成任务:任务ID:"+taskId);
}
/**
* 查询流程状态
* 判断流程是否正在执行,还是结束
*/
@Test
public void isProcessEnd() {
String processInstanceId="15001";
ProcessInstance pi=processEngine.getRuntimeService()//表示正在执行的流程实例和执行对象
.createProcessInstanceQuery()//创建流程实例查询
.processInstanceId(processInstanceId)//表示正在执行的流程实例和执行对象
.singleResult();
if(pi==null) {
System.out.println("流程已经结束");
}else {
System.out.println("流程没有结束");
}
}
}
执行流程相关的数据表
act_ru_execution 正在执行的执行对象表
act_hi_procinst 流程实例的历史表
act_ru_task 正在执行的任务表(只有节点是UserTask的时候该表存在数据)
act_hi_task 任务历史表(只有节点是UserTask的时候该表存在数据)
act_hi_actinst 所有活动节点的历史表
* 如果是单例流程(没有分支和聚合),那么流程实例ID和执行对象ID是相同
*一个流程实例只有一个,执行对象可以存在多个(如果存在分支和聚合)