Appearance
创建bpmn后需要将其部署到Activiti中,此时Activiti才能使用创建的流程,通过已部署的流程可以开启任务,任务的每一步称为流程,本文将讲解部署、任务、流程三个部分的基本操作。
1.流程部署
addClasspathResource
可以指定多个,bpmn文件会自动识别,可自定义名称。
java
@Test
public void testDeployment(){
// 1、获取引擎
ProcessEngineConfiguration configuration =
ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml");
ProcessEngine processEngine = configuration.buildProcessEngine();
// 2、得到RepositoryService实例
RepositoryService repositoryService = processEngine.getRepositoryService();
// 3、使用RepositoryService进行部署
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("bpmn/holiday.bpmn") // 添加bpmn资源
.addClasspathResource("bpmn/holiday.png") // 添加png资源
.name("出差申请流程")
.deploy();
// 4、输出部署信息
System.out.println("流程部署id:" + deployment.getId());
System.out.println("流程部署名称:" + deployment.getName());
}
压缩包部署
直接将bpmn文件统一压缩,假设有好几百个,压缩成一个xxx.zip
文件,然后执行下面代码,就会全部部署了,因为部署的是多个文件,所有可与设置name,但实际开发时,一般建议一个个部署。
java
@Test
public void deployProcessByZip() {
// 定义zip输入流
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("bpmn/holiday.zip");
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
// 获取repositoryService
RepositoryService repositoryService = processEngine.getRepositoryService();
// 流程部署
Deployment deployment = repositoryService.createDeployment().addZipInputStream(zipInputStream).deploy();
System.out.println("id:" + deployment.getId());
System.out.println("Name:" + deployment.getName());
}
2.任务相关操作
从创建-查询-完成任务顺序执行操作,利用Activiti提供的API实现,如果学过MybtaisPlus或SpringData会发现,其实就是将SQL转换为面向对象的查询方式,然后Activiti底层做了一些其他补充操作。
2.1 创建任务
上一步我们部署了一个流程,我们可以将部署的流程直接使用,创建一个任务
java
@Test
public void testStartProcess() {
// 创建ProcessEngineConfiguration
ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml");
// 通过ProcessEngineConfiguration创建ProcessEngine,此时会创建数据库
ProcessEngine processEngine = configuration.buildProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();
// 启动实例,这个id在bpmn文件中有定义
ProcessInstance holiday = runtimeService.startProcessInstanceByKey("holiday");
System.out.println("ProcessDefinition"+holiday.getProcessDefinitionId());
System.out.println("Id"+holiday.getId());
System.out.println("ActivityId"+holiday.getActivityId());
}
2.2 查询任务
获取holiday流程中李老师所需要处理的任务
java
@Test
public void testFindProcessInstance() {
ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml");
ProcessEngine processEngine = configuration.buildProcessEngine();
// 获取任务操作对象
TaskService taskService = processEngine.getTaskService();
// 获取holiday流程中李老师所需要处理的任务
List<Task> taskList = taskService.createTaskQuery().processDefinitionKey("holiday").taskAssignee("李老师").list();
for (Task task : taskList) {
System.out.println("流程定义id:"+task.getProcessDefinitionId());
System.out.println("分配给我任务的id:"+task.getId());
System.out.println("分配给我任务的命名:"+task.getAssignee());
System.out.println("分配给我任务名:"+task.getName());
}
}
2.3 完成任务
通过修改taskAssignee
处理人的名称,可以一步步完成任务。
java
@Test
public void completeTask() {
ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml");
ProcessEngine processEngine = configuration.buildProcessEngine();
TaskService taskService = processEngine.getTaskService();
// 如果只有一条任务,可以查询一条任务
Task task = taskService.createTaskQuery().processDefinitionKey("holiday").taskAssignee("李老师").singleResult();
// 有多个的情况不可以使用singleResult
// List<Task> taskList = taskService.createTaskQuery().processDefinitionKey("holiday").taskAssignee("李老师").list();
// 完成任务
taskService.complete(task.getId());
}
2.4 历史任务
需要注意的是即使流程定义已经删除了,流程执行的历史信息依然保存在activiti的act_hi_*
相关的表中,还是可以查询流程执行的历史信息,可以通过HistoryService
来查看相关的历史记录。
java
public void findHistoryInfo() {
// 获取引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取HistoryService
HistoryService historyService = processEngine.getHistoryService();
// 获取 actinst表的查询对象
HistoricActivityInstanceQuery instanceQuery = historyService.createHistoricActivityInstanceQuery();
// 查询 actinst表,条件:根据 InstanceId 查询
// instanceQuery.processInstanceId("2503");
// 查询 actinst表,条件:根据 DefinitionId 查询
instanceQuery.processDefinitionId("holiday:1:3");
// 增加排序操作,orderByHistoricActivityInstanceStartTime 根据开始时间排序 asc 升序
instanceQuery.orderByHistoricActivityInstanceStartTime().asc();
// 查询所有内容
List<HistoricActivityInstance> activityInstanceList = instanceQuery.list();
// 输出
for (HistoricActivityInstance hi : activityInstanceList) {
System.out.println(hi.getActivityId());
System.out.println(hi.getActivityName());
System.out.println(hi.getProcessDefinitionId());
System.out.println(hi.getProcessInstanceId());
System.out.println("<==========================>");
}
}
::: tips
java
ProcessEngineConfiguration configuration =
ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml");
ProcessEngine processEngine = configuration.buildProcessEngine();
由于我们是严格按照官方的默认配置格式进行配置,因此上述两句代码可简化成
java
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
:::
3.流程相关操作
已经部署的流程可与查看流程定义的基本信息,删除流程,以及如果找不到bpmn或其他源资源文件,Activiti可以从数据库查询到这些文件,这些文件以Blob二进制方式存储。
3.1 查询流程定义信息
java
public void queryProcessDefinition() {
ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml");
ProcessEngine processEngine = configuration.buildProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().processDefinitionKey("holiday").orderByProcessDefinitionVersion().desc().list();
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("DeploymentId="+processDefinition.getDeploymentId());
}
}
输出
shell
id=holiday:2:7503
name=holiday
key=holiday
Version=2
DeploymentId =7501
id=holiday:1:3
name=holiday
key=holiday
Version=1
DeploymentId =1
3.2 删除流程
默认如果有正在执行中的任务,则无法删除流程,会抛出异常,提示有外键冲突。说明:历史表中的数据不会被删除。
java
public void deleteDeployment() {
ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml");
ProcessEngine processEngine = configuration.buildProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey("holiday").orderByProcessDefinitionVersion().desc().list();
// 如果不设置为true,如果有正在执行中的任务,则无法删除流程,会抛出异常
// 设置为true那些正在执行的任务会被直接删除
repositoryService.deleteDeployment(list.get(0).getDeploymentId(), true);
}
3.3 流程资源下载
现在我们的流程资源文件已经上传到数据库了,如果其他用户想要查看这些资源文件,或者因为一些意外情况导致文件丢失,可以从数据库中把资源文件下载到本地。使用commons-io.jar 解决IO的操作,引入commons-io依赖包(文章开头引入过就不用再引入了)
xml
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
通过流程定义对象获取流程定义资源,获取bpmn文件,如果有其他文件,也可以使用类似方法进行下载
java
public void downloadFile() throws IOException {
//创建流程引擎配置文件
ProcessEngineConfiguration configuration
= ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cgf.xml","processEngineConfiguration");
//通过配置文件,创建流程
ProcessEngine processEngine = configuration.buildProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
//1repositoryService 获取相应的数据
ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().processDefinitionKey("holiday").singleResult();
String deploymentId = definition.getDeploymentId();
InputStream xmlFileInputStream = repositoryService.getResourceAsStream(deploymentId,definition.getResourceName());
InputStream pngInputStream = repositoryService.getResourceAsStream(deploymentId, definition.getDiagramResourceName());
//2转成输出流,放到本地文件夹下
FileOutputStream xmlFileOutputStream=new FileOutputStream(new File("d:/holiday.bpmn20.xml"));
FileOutputStream pngFileOutputStream=new FileOutputStream(new File("d:/holiday.png"));
//3工具类把输入流转成输出流
IOUtils.copy(xmlFileInputStream,xmlFileOutputStream);
IOUtils.copy(pngInputStream,pngFileOutputStream);
//4关流
pngFileOutputStream.close();
xmlFileOutputStream.close();
pngInputStream.close();
xmlFileInputStream.close();
}