一、准备工作

二、介绍与配置

1. 表介绍

参考文档:Activiti 数据库表结构
Activiti 的表都以ACT_开头。 第二部分是表示表的用途的两个字母标识。 用途也和服务的 API 对应

  • ACT_RE_*: 'RE’表示 repository。 这个前缀的表包含了流程定义和流程静态资源 (图片, 规则,等等)。
  • ACT_RU_*: 'RU’表示 runtime。 这些运行时的表,包含流程实例,任务,变量,异步任务, 等运行中的数据。 Activiti只在流程实例执行过程中保存这些数据, 在流程结束时就会删 除这些记录。 这样运行时表可以一直很小速度很快。
  • ACT_HI_*: 'HI’表示 history。 这些表包含历史数据,比如历史流程实例, 变量,任务等 等。
  • ACT_GE_*: GE表示 general。通用数据, 用于不同场景下

2. Activiti 服务架构图

在新版本中,我们通过实验可以发现 IdentityService,FormService 两个Serivce 都已经删除了。 所以后面我们对于这两个 Service 也不讲解了,但老版本中还是有这两个 Service,同学们需要了解 一下

3. 配置

maven

    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <slf4j.version>1.6.6</slf4j.version>
        <log4j.version>1.2.12</log4j.version>
        <activiti.version>7.1.0.M6</activiti.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-engine</artifactId>
            <version>${activiti.version}</version>
        </dependency>

        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring</artifactId>
            <version>${activiti.version}</version>
        </dependency>

        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-bpmn-model</artifactId>
            <version>${activiti.version}</version>
        </dependency>

        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-bpmn-converter</artifactId>
            <version>${activiti.version}</version>
        </dependency>

        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-json-converter</artifactId>
            <version>${activiti.version}</version>
        </dependency>

        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-bpmn-layout</artifactId>
            <version>${activiti.version}</version>
        </dependency>

        <dependency>
            <groupId>org.activiti.cloud</groupId>
            <artifactId>activiti-cloud-services-api</artifactId>
            <version>7.0.0.Beta1</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.40</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

        <!-- log start -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j.version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
        <!-- log end -->

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>

        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.4</version>
        </dependency>

    </dependencies>
    
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/contex http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!--数据源配置dbcp-->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/activiti" />
        <property name="username" value="root" />
        <property name="password" value="root" />
    </bean>
    <!--activiti单独运行的ProcessEngine配置对象(processEngineConfiguration),使用单独启动方式 默认情况下:bean的id=processEngineConfiguration -->

    <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
    <!--代表数据源-->
    <property name="dataSource" ref="dataSource"></property>


   <!-- <property name="jdbcDriver" value="com.mysql.jdbc.Driver" /> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/activiti" /> <property name="jdbcUsername" value="root" /> <property name="jdbcPassword" value="root" />-->
    <!--代表是否生成表结构-->
    <property name="databaseSchemaUpdate" value="true"/>
    </bean>
</beans>
package com;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.ProcessEngines;
import org.junit.Test;

/** * @author 夏天 * @date 2020年11月28日 15:20 */
public class test {
   
    @Test
    public void testGenTable() {
   
        //条件:1.activiti配置文件名称:activiti.cfg.xml 2.bean的id="processEngineConfiguration"
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        System.out.println(processEngine);

        // HistoryService historyService = processEngine.getHistoryService();

    }

    @Test
    public void testGenTable1() {
   
        //1.创建ProcessEngineConfiguration对象 第一个参数:配置文件名称 第二个参数是processEngineConfiguration的bean的id
        ProcessEngineConfiguration configuration = ProcessEngineConfiguration
                .createProcessEngineConfigurationFromResource("activiti.cfg.xml", "processEngineConfiguration01");
        //2.创建ProcesEngine对象
        ProcessEngine processEngine = configuration.buildProcessEngine();
        //3.输出processEngine对象
        System.out.println(processEngine);
    }

    @Test
    public void test3() {
   
        ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration();
        configuration.setJdbcDriver("com.mysql.jdbc.Driver");
        configuration.setJdbcUrl("jdbc:mysql://localhost:3306/activiti");
        configuration.setJdbcUsername("root");
        configuration.setJdbcPassword("1234");
        configuration.setDatabaseSchemaUpdate("true"); //设置启动时候创建表
        ProcessEngine processEngine = configuration.buildProcessEngine();
        System.out.println(processEngine);
    }
}

以上三种方式都可以创建表 在7.1.0.M6版本共创建25张表

4. Service 总览

名称 介绍
RepositoryService activiti 的资源管理类
RuntimeService activiti 的流程运行管理类
TaskService activiti 的任务管理类
HistoryService activiti 的历史管理类
ManagerService activiti 的引擎管理类

前4种为常用的

各种service介绍

1 RepositoryService

是 activiti的资源管理类,提供了管理和控制流程发布包和流程定义的操作。使用工作流建模工 具设计的业务流程图需要使用此 service 将流程定义文件的内容部署到计算机。 除了部署流程定义以外还可以: 查询引擎中的发布包和流程定义。 暂停或激活发布包,对应全部和特定流程定义。 暂停意味着它们不能再执行任何操作了,激活 是对应的反向操作。 获得多种资源,像是包含在发布包里的文件, 或引擎自动生成的流程图。 获得流程定义的 pojo 版本, 可以用来通过 java 解析流程,而不必通过 xml。

2 RuntimeService

它是 activiti的流程运行管理类。可以从这个服务类中获取很多关于流程执行相关的信息

3 TaskService

是 activiti的任务管理类。可以从这个类中获取任务的信息。

4 HistoryService

是 activiti 的历史管理类,可以查询历史信息,执行流程时,引擎会保存很多数据(根据配置),比 如流程实例启动时间,任务的参与者, 完成任务的时间,每个流程实例的执行路径,等等。 这个 服务主要通过查询功能来获得这些数据。

5 ManagementService

是 activiti的引擎管理类,提供了对 Activiti 流程引擎的管理和维护功能,这些功能不在工作流驱动 的应用程序中使用,主要用于 Activiti 系统的日常维护

三、使用

整体步骤:

  1. 绘制流程图 并指定流程id 和每一步的参与者的名字
  2. 部署流程 类似于java中的定义类
  3. 创建实例启动流程 类似java中的new一个对象
  4. 创建实例启动后 任务就已经按照流程图开始走了 需要每一步的人处理完任务后 下一人才能处理这个任务

在以下例子中:
填写请假:张三
部门经理审批:李四
总经理审批:王五
当创建一个实例后 张三就会出现任务。在张三没完成之前 李四 王五(之后步骤的参与者) 是没有这个任务的
当张三完成该任务 李四便具有该任务的 并进行处理
直至任务达到结尾 任务结束 在数据库表中可以明确查看到每位参与者获得到任务与处理任务的时间以及一些任务的相关信息

把.bpmn文件转换图片形式

  1. 把.bpmn转换为xml
  2. 生成图片(乱码问题 :设置项目的编码为utf-8即可)
  3. 保存xml图片即可

    乱码解决
    -Dfile.encoding=UTF-8

流程定义

  1. 绘制流程
    2. 指定流程定义 key

建议:相同的业务流程,流程定义的 key 名字定义一样,比如,如果需要创建新的业务流程,请假 流程则使用新的 key。

  1. 指定任务负责人

在 properties 视图指定每个任务结点的负责人, 比如下边是填写请假单的负责人为 zhangsan

流程部署

 public static void main(String[] args) {
   
        //1. 创建processEngine对象
        //getDefaultProcessEngine会去activiti.cfg.xml下面找配置
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2. 得到RepositoryService实例
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //3. 进行部署
        Deployment deploy = repositoryService.createDeployment()
                .addClasspathResource("myholidy.bpmn") //添加bpmn资源
                .addClasspathResource("myholidy.png") //添加图片资源
                .name("请假申请单流程")
                .deploy();// 进行部署
        //4. 输出部署的一些信息
        System.out.println(deploy.getName());
        System.out.println(deploy.getId());
    }

部署后这三张表会增加对应的记录

  • act_re_deployment 部署信息
  • act_re_procdef 流程定义的一些信息
  • act_ge_bytearray 流程定义的bpmn文件及png文件

启动实例

流程定义的key的方法
1.

2.

/** * @author 夏天 * @date 2020年11月28日 16:32 * 启动流程实例 : 前提是先已经完成流程定义的部署工作 */
public class ActivitiStartInstance {
   

    public static void main(String[] args) {
   
        //1. 得到一个ProcessEngine对象
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2. 得到RunService对象
        RuntimeService runtimeService = processEngine.getRuntimeService();
        //3. 创建流程实例 需要知道流程定义的key
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holiday");
        //4. 输出流程实例的相关信息
        System.out.println("流程部署id: " + processInstance.getDeploymentId()); //null
        System.out.println("流程定义id: " + processInstance.getProcessDefinitionId()); //holiday:1:7504
        System.out.println("流程实例id: " + processInstance.getId());           //20001
        System.out.println("活动id: " + processInstance.getActivityId());     //null

    }
}


背后影响的表:

  • act_hi_actinst 已完成的活动信息
  • act_hi_identitylink 参与者信息
  • act_hi_procinst 流程实例
  • act_hi_taskinst 任务实例
  • act_ru_execution 执行表
  • act_ru_identitylink 参与者信息
  • act_ru_task 任务

查询任务


/** * 查询当前用户的任务列表 */
public class ActivitiTaskQuery {
   

    //王五完成自己任务列表的查询
    @Test
    public void 王五() {
   
        //1.得到ProcessEngine对象
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2.得到TaskService对象
        TaskService taskService = processEngine.getTaskService();

        //3.根据流程定义的key,负责人assignee来实现当前用户的任务列表查询
        Task task = taskService.createTaskQuery()
                .processDefinitionKey("holiday")
                .taskAssignee("王五")
                .singleResult();

        //4.任务列表的展示
        System.out.println("流程实例ID:" + task.getProcessInstanceId());
        System.out.println("任务ID:" + task.getId());  //5002
        System.out.println("任务负责人:" + task.getAssignee());
        System.out.println("任务名称:" + task.getName());


    }

    //lishi完成自己任务列表的查询
    @Test
    public void 李四() {
   
        //1.得到ProcessEngine对象
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2.得到TaskService对象
        TaskService taskService = processEngine.getTaskService();

        //3.根据流程定义的key,负责人assignee来实现当前用户的任务列表查询
        Task task = taskService.createTaskQuery()
                .processDefinitionKey("holiday")
                .taskAssignee("李四")
                .singleResult();

        //4.任务列表的展示
        System.out.println("流程实例ID:" + task.getProcessInstanceId());
        System.out.println("任务ID:" + task.getId());  //5002
        System.out.println("任务负责人:" + task.getAssignee());
        System.out.println("任务名称:" + task.getName());


    }

    //张三任务列表的查询
    @Test
    public void 张三() {
   
        //1.得到ProcessEngine对象
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2.得到TaskService对象
        TaskService taskService = processEngine.getTaskService();

        //3.根据流程定义的key,负责人assignee来实现当前用户的任务列表查询
        List<Task> taskList = taskService.createTaskQuery()
                .processDefinitionKey("holiday")
                .taskAssignee("张三")
                .list();

        //4.任务列表的展示
        for (Task task : taskList) {
   
            System.out.println("流程实例ID:" + task.getProcessInstanceId());
            System.out.println("任务ID:" + task.getId());
            System.out.println("任务负责人:" + task.getAssignee());
            System.out.println("任务名称:" + task.getName());
        }

    }
}


处理任务

注意:查看任务表(act_ru_task) 王五和李四目前都没有任务只有张三具有任务 因为创建实例后张三为第一步骤需要填写请假单填写完成才可以继续后边的步骤
处理当前用户的任务
背后操作的表:

  • act_hi_actinst 已完成的活动信息
  • act_hi_identitylink 历史参与者信息
  • act_hi_taskinst 历史任务实例
  • act_ru_identitylink 当前参与者信息
  • act_ru_task 当前任务

/** * * 注意:查看任务表(act_ru_task) 王五和李四目前都没有任务只有张三具有任务 因为创建实例后张三为第一步骤需要填写请假单填写完成才可以继续后边的步骤 * 处理当前用户的任务 * 背后操作的表: * act_hi_actinst 已完成的活动信息 * act_hi_identitylink 历史参与者信息 * act_hi_taskinst 历史任务实例 * act_ru_identitylink 当前参与者信息 * act_ru_task 当前任务 */
public class ActivitiCompleteTask {
   

    //查询当前用户wangwu的任务并处理掉
    @Test
    public void 王五() {
   
        //1.得到ProcessEngine对象
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2.得到TaskService对象
        TaskService taskService = processEngine.getTaskService();

        //3.查询当前用户的任务
        Task task = taskService.createTaskQuery()
                .processDefinitionKey("holiday")
                .taskAssignee("王五")
                .singleResult();

        //4.处理任务,结合当前用户任务列表的查询操作的话,任务ID:task.getId()
        taskService.complete(task.getId());

        //5.输出任务的id
        System.out.println(task.getId());
    }


    //李四完成自己的任务
    @Test
    public void 李四() {
   
        //1.得到ProcessEngine对象
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2.得到TaskService对象
        TaskService taskService = processEngine.getTaskService();

        Task task = taskService.createTaskQuery()
                .processDefinitionKey("holiday")
                .taskAssignee("李四")
                .singleResult();
        //3.处理任务,结合当前用户任务列表的查询操作的话,任务ID:5002
        taskService.complete(task.getId());
    }


    //张三完成自己的任务
    @Test
    public void 张三() {
   
        //1.得到ProcessEngine对象
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2.得到TaskService对象
        TaskService taskService = processEngine.getTaskService();
        Task task = taskService.createTaskQuery()
                .processDefinitionKey("holiday")
                .taskAssignee("张三")
                .singleResult();
        //3.处理任务,结合当前用户任务列表的查询操作的话,任务ID:2505
        taskService.complete(task.getId());
    }
}

总结

  • 1 .Activiti的架构说明
    ProcessEngineConfi guration类,主要作用是加载activiti.cfg.xeml配置文件
    ProcessEngine类作用是帮助我们可以快速得到各个Service接口,并且可以生成activiti的工作环境25张表生成Serivce接口:作用:可以快速实现数据库25张表的操作。
    Eep osi t orySerwice
    EuntineServiceTaskServiceHistoryService
  • 2.BPMN的ActivitiDesigner插件
    IDEA工具中安装插件注意细节
  • 3.画出流程定义图
  • 4.部署流程定义
    方式一:单个文件( bpmn文件,nz文件)
    方式二∶先将byrmn文件, pn文件压缩成zip文件。但是activiti最终也是以单个文件形式保存,说明activiti进行了解压工作DepLoyment depLoyment = repositoryService.createDepLoyment()
    .addCLasspathResource( “diagram/holiday .bpmn”)//添加bpmn资源
    .addCLasspathResource( “diagram/ hoLiday .png”)
    .name(“请假申请单流程”")
    .deploy ();
  • 5.启动流程实例RuntimeService
    startProcessInstanceByKey(“key”)
  • 6.查看任务
    TaskServicetaskservice.createTaskQuery()
  • 7.完成任务
    Taskservice taskservice.complete(task.getId());/ /参数为任务ID

流程定义

1. 查询流程定义信息

/** * 查询流程定义信息 */
public class _01QueryProcessDefinition {
   


    public static void main(String[] args) {
   
        //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") //根据key查询流程
                .orderByProcessDefinitionVersion() //排序方式
                .desc().list(); // 降序 全部

        //5.输出流程定义信息
        for(ProcessDefinition processDefinition :list){
   
            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:4
流程定义名称:请假流程
流程定义的Key:holiday
流程定义的版本号:1
流程部署的ID:1

2. 删除流程定义信息

注意事项:

  1. 当我们正在执行的这一套流程没有完全审批结束的时候,此时如果要删除流程定义信息就会失败
  2. 如果公司层面要强制删除,可以使用repositoryService.deleteDeployment(“1”,true);
    参数true代表级联删除,此时就会先删除没有完成的流程结点,最后就可以删除流程定义信息 false的值代表不级联

背后影响的表:

  • act_re_deployment 部署信息
  • act_re_procdef 流程定义的一些信息
  • act_ge_bytearray 流程定义的bpmn文件及png文件
/** * 删除已经部署的流程定义 * * 背后影响的表: * act_ge_bytearray act_re_deployment act_re_procdef */
public class _02DeleteProcessDefinition {
   

    public static void main(String[] args) {
   
        //1.得到ProcessEngine对象
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2.创建RepositoryService对象
        RepositoryService repositoryService = processEngine.getRepositoryService();

        //3.执行删除流程定义 参数代表流程部署的id
        repositoryService.deleteDeployment("1");
    }
}

3. 获取资源文件

/** * 需求: * 1.从Activiti的act_ge_bytearray表中读取两个资源文件 * 2.将两个资源文件保存到路径: G:\Activiti7开发计划\Activiti7-day03\资料 * <p> * 技术方案: * 1.第一种方式使用actviti的api来实现 * 2.第二种方式:其实就是原理层面,可以使用jdbc的对blob类型,clob类型数据的读取,并保存 * IO流转换,最好commons-io.jar包可以轻松解决IO操作 * <p> * 真实应用场景:用户想查看这个请假流程具体有哪些步骤要走? */
public class _03QueryBpmnFile {
   

    public static void main(String[] args) 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());
        System.out.println(System.getProperty("user.dir"));
        //8.构建出OutputStream流
        OutputStream pngOs =
                new FileOutputStream(System.getProperty("user.dir") + "/" + processDefinition.getDiagramResourceName());

        OutputStream bpmnOs =
                new FileOutputStream(System.getProperty("user.dir") + "/" + processDefinition.getResourceName());

        //9.输入流,输出流的转换 commons-io-xx.jar中的方法
        IOUtils.copy(pngIs, pngOs);
        IOUtils.copy(bpmnIs, bpmnOs);
        //10.关闭流
        pngOs.close();
        bpmnOs.close();
        pngIs.close();
        bpmnIs.close();
    }
}

4. 已完成流程历史信息的查看

操作流程定义为挂起状态,该流程定义下边所有的流程实例全部暂停: 流程定义为挂起状态该流程定义将不允许启动新的流程实例,同时该流程定义下所有的流程实例将 全部挂起暂停执行。

/** * @author 夏天 * @date 2020年11月28日 18:59 * 历史数据的查看 */
public class _04HistoryQuery {
   
    public static void main(String[] args) {
   
        //1.得到ProcessEngine对象
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2.得到HistoryService
        HistoryService historyService = processEngine.getHistoryService();
        //3.得到HistoricActivitiInstanceQuery对象
        HistoricActivityInstanceQuery historicActivityInstanceQuery = historyService.createHistoricActivityInstanceQuery();
        //4.执行查询
        List<HistoricActivityInstance> list = historicActivityInstanceQuery.orderByHistoricActivityInstanceStartTime().asc().list();
        //5.遍历查询结果
        for (HistoricActivityInstance instance : list) {
   
            System.out.println(instance.getActivityId());
            System.out.println(instance.getActivityName());
            System.out.println(instance.getProcessDefinitionId());
            System.out.println(instance.getProcessInstanceId());
            System.out.println("=============================");
        }

    }
}

结果

_2
StartEvent
holiday:1:4
2501
=============================
_3
填写请假
holiday:1:4
2501
=============================
_7
部门经理审批
holiday:1:4
2501
=============================
_6
总经理审
holiday:1:4
2501
=============================
_4
EndEvent
holiday:1:4
2501
=============================

5. 关联 businessKey

需求: 在 activiti实际应用时,查询流程实例列表时可能要显示出业务系统的一些相关信息,比如:查询当 前运行的请假流程列表需要将请假单名称、请假天数等信息显示出来,请假天数等信息在业务系统 中存在,而并没有在 activiti数据库中存在,所以是无法通过 activiti的 api查询到请假天数等信息。
实现
在查询流程实例时,通过 businessKey(业务标识 )关联查询业务系统的请假单表,查询出请假天 数等信息。 通过下面的代码就可以获取 activiti中所对应实例保存的业务 Key。而这个业务Key 一般都会保存相 关联的业务操作表的主键,再通过主键 ID 去查询业务信息,比如通过请假单的 ID,去查询更多的 请假信息(请假人,请假时间,请假天数,请假事由等) String businessKey = processInstance.getBusinessKey();

在 activiti的 act_ru_execution 表,字段 BUSINESS_KEY就是存放业务 KEY 的


代码

/** * 启动流程实例,添加进businessKey * * 本质:act_ru_execution表中的businessKey的字段要存入业务标识 */
public class _07BusinessKeyAdd {
   


   public static void main(String[] args) {
   
       //1.得到ProcessEngine对象
       ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

       //2.得到RuntimeService对象
       RuntimeService runtimeService = processEngine.getRuntimeService();

       //3.启动流程实例,同时还要指定业务标识businessKey 它本身就是请假单的id
       //第一个参数:是指流程定义key
       //第二个参数:业务标识businessKey
       ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holiday", "1001");

       //4.输出processInstance相关的属性,取出businessKey使用:processInstance.getBusinessKey()
       System.out.println(processInstance.getBusinessKey());

   }
}

6. 激活、挂机流程实例

全部流程实例挂起与激活

  • 影响的表:
  • ACT_RE_PROCDEF 修改当前实例的状态 1:激活 2:挂起
  • ACT_RU_EXECUTION 修改SUSPENSION_STATE 1:激活 2:挂起
  • ACT_RU_TASK 修改SUSPENSION_STATE 1:激活 2:挂起

/** * 全部流程实例挂起与激活 * 影响的表: * ACT_RE_PROCDEF 修改当前实例的状态 1:激活 2:挂起 * ACT_RU_EXECUTION 修改SUSPENSION_STATE 1:激活 2:挂起 * ACT_RU_TASK 修改SUSPENSION_STATE 1:激活 2:挂起 */
public class _05SuspendProcessInstance {
   


    public static void main(String[] args) {
   
        //1.得到ProcessEngine对象
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2.得到RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();

        //3.查询流程定义的对象
        //注意这次操作的是ACT_RE_PROCDEF表 如果该表中的key 不唯一 则需要把singleResult改为list 根据业务需求把需要的挂起或激活
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey("holiday").singleResult();

        //4.得到当前流程定义的实例是否都为暂停状态
        boolean suspended = processDefinition.isSuspended();

        String processDefinitionId = processDefinition.getId();
        //5.判断
        if(suspended){
   
            //说明是暂停,就可以激活操作
            repositoryService.activateProcessDefinitionById(processDefinitionId,true
            ,null);
            System.out.println("流程定义:"+processDefinitionId+"激活");
        }else{
   
            repositoryService.suspendProcessDefinitionById(processDefinitionId,true,null);
            System.out.println("流程定义:"+processDefinitionId+"挂起");
        }

    }
}

7. 激活、挂起单个实例

影响的表
ACT_RU_TASK
ACT_RU_EXECUTION

/** * 单个流程实例挂起与激活 * 影响表: * ACT_RU_TASK * ACT_RU_EXECUTION */
public class _06SuspendProcessInstance {
   


    public static void main(String[] args) {
   
        //1.得到ProcessEngine对象
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        //2.得到RuntimeService
        RuntimeService runtimeService = processEngine.getRuntimeService();

        //3.查询流程实例对象
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId("15001").singleResult();
        //4.得到当前流程定义的实例是否都为暂停状态
        boolean suspended = processInstance.isSuspended();

       String processInstanceId = processInstance.getId();
        //5.判断
        if(suspended){
   
            //说明是暂停,就可以激活操作
            runtimeService.activateProcessInstanceById(processInstanceId);
            System.out.println("流程:"+processInstanceId+"激活");
        }else{
   
            runtimeService.suspendProcessInstanceById(processInstanceId);
            System.out.println("流程定义:"+processInstanceId+"挂起");
        }

    }
}

8. 流程挂起和激活总结

补充:流程和实例的区别
流程:值绘制图部署后的 叫流程(比如请假的流程) 比如java中的类 只有一个
实例 :指的是根据流程启动(比如每次请假都是一个实例)的每个任务 实例(多个人请假)可以有很多个 但是一般流程(请假的步骤)只有一个

全部挂起、激活是根据ACT_RE_PROCDEF中的key(id也可以)进行流程挂起和激活的
根据流程id

  • repositoryService.activateProcessDefinitionById() 根据流程id激活流程
  • repositoryService.activateProcessDefinitionByKey() 根据流程key激活流程
  • repositoryService.suspendProcessDefinitionById 根据流程id挂起流程
  • repositoryService.suspendProcessDefinitionByKey(); 根据流程key挂起

参数介绍:
void suspendProcessDefinitionById(String processDefinitionId, boolean suspendProcessInstances, Date suspensionDate);

  • processDefinitionId :挂起(暂停)流程的id
  • activateProcessInstances 是否同时挂起(暂停)当前流程的所有实例
    • true:挂起(暂停当前所有的实例) 比如:当前请假流程不可以用了 并且把没完成的请假状态都暂停不允许继续进行了
    • false:只会暂停当前流程 不会影响实例。比如:当前请假流程不可以用了,但是已经开始的请假但为结束的不受影响可以继续进行
  • suspensionDate :流程定义将被暂停的日期。 如果为null,则立即暂停过程定义。 注意:作业执行者必须处于活动状态才能使用它!
    • new Date(System.currentTimeMillis() + 1000 * 60 * 2)); 两分钟以后才会进行挂起操作 <mark>测试后暂不好使</mark>

实验 activateProcessInstances为false情况


suspensionDate 设置两分钟后执行会在该表中增加一条定时任务

单独挂起、激活是根据ACT_RU_EXECUTION中的id也就是启动实例后的id进行挂起和激活的

  • runtimeService.activateProcessInstanceById(processInstanceId); 根据实例id激活单个实例
  • runtimeService.suspendProcessInstanceById(processInstanceId);根据实例id挂起单个实例

补充
处理挂起(暂停)的任务会抛出异常org.activiti.engine.ActivitiException: Cannot complete a suspended task