Skip to content

创建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();
}