Activiti

工作流的概念

  • 工作流(Workflow),即通过计算机对业务流程自动化执行管理
  • 它主要解决的是:使多个参与者之间按照某种预定义的规则自动进行传递文件、信息或任务的过程,从而实现某个预期的业务目标,或者促进此目标的实现

Activiti简介

  • Activiti是一个工作流引擎,可以将业务系统中复杂的业务流程抽取出来,使用建模语言BPMN进行定义
  • 业务流程按照预先定义的流程进行执行,系统的流程由activiti进行管理;可以减少系统由于流程变更进行系统改造的工作量,提高系统健壮性,减少了开发维护成本

BPMN

  • BPM(Business Process Management),业务流程管理,是一种规范化的构造端到端的业务流程,以持续提高组织业务效率
  • BPMN(Business Process Model AndNotation),业务流程模型和符号,是由BPMI开发的一套标准的业务流程建模符号,使用BPMN提供的符号可以创建业务流程

  • BPMN详细介绍:http://www.mossle.com/docs/jbpm4devguide/html/bpmn2.html

  • BPMN实例:

    BPMN实例

Activiti使用步骤

  1. 将相关jar包、API下载并部署;把工作流环境与业务系统的环境集成在一起
  2. 用activiti流程建模工具定义业务流程,建立.bpmn文件
  3. activiti部署业务流程定义(.bpmn文件);即使用activiti提供的api把流程定义的内容存储在数据库中
  4. 启动一个流程实例,开始一次业务流程的运行

tips:

  1. 在系统的业务流程交给activiti管理后,通过activiti就可以查询当前流程执行到哪了、当前用户需要办理什么任务了;这些activiti帮我们管理了,不需要开发再编写sql语句查询

Activiti开发环境准备

  • 开发工具安装Activiti流程定义插件

    IDEA工具可以安装actiBPM

  • 下载jar包或Maven项目添加Activiti依赖

    <properties>
        <activiti.version>7.0.0.Beta1</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>
        <!-- bpmn 模型处理 -->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-bpmn-model</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <!-- bpmn 转换 -->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-bpmn-converter</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <!-- bpmn json转换 -->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-json-converter</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <!-- bpmn 布局 -->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-bpmn-layout</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <!-- bpmn 云支持 -->
        <dependency>
            <groupId>org.activiti.cloud</groupId>
            <artifactId>activiti-cloud-services-api</artifactId>
            <version>${activiti.version}</version>
        </dependency>
    </dependencies>
    
  • 建立Activiti配置文件

    在项目的resources下创建activiti.cfg.xml文件

    <?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">
        <!--默认id不变-->
        <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
            <!--配置数据库相关信息-->
            <property name="jdbcDriver" value="com.mysql.cj.jdbc.Driver"/>
            <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/activiti?serverTimezone=GMT%2B8"/>
            <property name="jdbcUsername" value="root"/>
            <property name="jdbcPassword" value="password"/>
            <!--activiti表生成策略;true:如果库中存在相应的表 直接使用-->
            <property name="databaseSchemaUpdate" value="true"/>
        </bean>
    </beans>
    
  • 安装支持Activiti的数据库:Mysql、Oracle、H2等

    1. 建立 activiti专用数据库或表空间

    2. 使用activiti提供的默认方式来创建表

      import org.activiti.engine.ProcessEngine;
      import org.activiti.engine.ProcessEngines;
      import org.junit.Test;
           
      public class TestCreateTable {
          @Test
          public void createTable(){
              // 使用activiti提供的工具类ProcessEngines,调用方法getDefaultProcessEngine
              // 该方法会从resources下读取名字为activiti.cfg.xml的文件
              // 创建ProcessEngine时,就会创建相关的表
              ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
          }
      }
      

Activiti表结构

Activiti部署完成后,会在数据库中自动建立25张表,具体分为以下几类

  • 通用数据(act_ge_)
表名 解释
act_ge_bytearray 二进制数据表,存储通用的流程定义和流程资源。
act_ge_property 系统相关属性,属性数据表存储整个流程引擎级别的数据,初始化表结构时,会默认插入三条记录。
  • 流程定义表(act_re_)
表名 解释
act_re_deployment 部署信息表
act_re_model 流程设计模型部署表
act_re_procdef 流程定义数据表
  • 运行实例表(act_ru_)
表名 解释
act_ru_deadletter_job 作业死亡信息表,作业失败超过重试次数
act_ru_event_subscr 运行时事件表
act_ru_execution 运行时流程执行实例表
act_ru_identitylink 运行时用户信息表
act_ru_integration 运行时积分表
act_ru_job 运行时作业信息表
act_ru_suspended_job 运行时作业暂停表
act_ru_task 运行时任务信息表
act_ru_timer_job 运行时定时器作业表
act_ru_variable 运行时变量信息表
  • 历史流程表(act_hi_)
表名 解释
act_hi_actinst 历史节点表
act_hi_attachment 历史附件表
act_hi_comment 历史意见表
act_hi_detail 历史详情表,提供历史变量的查询
act_hi_detail 历史流程用户信息表
act_hi_procinst 历史流程实例表
act_hi_taskinst 历史任务实例表
act_hi_varinst 历史变量表
  • 其他表
表名 解释
act_evt_log 流程引擎的通用事件日志记录表
act_procdef_info 流程定义的动态变更信息

Activiti类结构与接口

Activiti框架中有如下类结构:

activiti类结构

如图可知,可以通过前面用过的ProcessEngine对象,获取一系列service对象,从而对不同的表进行操作

工作流引擎创建

  • 默认创建方式

    activiti.cfg.xml文件名及路径固定,且activiti.cfg.xml文件中有processEngineConfiguration的配置,可以使用如下方式创建processEngine

    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    
  • 一般创建方式

    先构建processEngineConfiguration,进一步构建processEngine

    ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml");
    ProcessEngine processEngine = processEngineConfiguration.buildProcessEngine();
    

Service服务接口

Service是由工作流引擎提供的,用于工作流部署、执行、管理的服务接口

创建方式

通过ProcessEngine创建

RuntimeService runtimeService = processEngine.getRuntimeService();
Service总览
Service 用途
RepositoryService 资源管理
RuntimeService 流程定义的动态变更信息
TaskService 任务管理
HistoryService 历史管理
ManagerService 引擎管理

流程设计及部署测试

  • 在项目的resources目录下建立xxx.bpmn文件,并使用插件画出流程

    出差申请

  • 创建该bpmn的xxx.png文件,并与该bpmn放在同一目录下

  • 通过RepositoryService部署流程

    @Test
    public void testDeployment(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //定义流程的名字,并把bpmn与png进行入库
        Deployment deploy = repositoryService.createDeployment()
                .name("出差申请流程")
                .addClasspathResource("bpmn/evection.bpmn")
                .addClasspathResource("bpmn/evection.png")
                .deploy();
        //输出部署信息
        System.out.println("流程部署id=" + deploy.getId());
        System.out.println("流程部署名字=" + deploy.getName());
    }
    

    一次部署会在ACT_RE_DEPLOYMENT表中生成一条记录;ACT_RE_PROCDEF中生成流程定义信息;ACT_RE_DEPLOYMENT与ACT_RE_PROCDEF是一对多的关系

    bpmn与png放入了ACT_GE_BYTEARRAY 表中

    tips:

    1. 当我们的流程非常多时,可以将bpmn于png打包进行批量部署
  • 启动流程实例

    @Test
    public void testStartProcess(){
        //获取runtimeService
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        RuntimeService runtimeService = processEngine.getRuntimeService();
        //根据流程的key启动流程
        ProcessInstance instance = runtimeService.startProcessInstanceByKey("MyEvection");
        //查看流程
        System.out.println("流程定义ID:" + instance.getProcessDefinitionId());
        System.out.println("流程实例ID:" + instance.getId());
        System.out.println("当前活动的ID:" + instance.getActivityId());
    }
    

    控制台输出的内容为:

    流程定义ID:MyEvection:1:4
    流程实例ID:2501
    当前活动的ID:null
    
  • 个人待执行任务查询

    @Test
    public void testFindPersonalTaskList(){
        //获取taskService
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = processEngine.getTaskService();
        //根据流程key 和 任务负责人名字 查询任务
        List<Task> taskList = taskService.createTaskQuery()
                .processDefinitionKey("MyEvection")
                .taskAssignee("sam")
                .list();
        //输出
        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());
        }
    }
    

    控制台输出:

    流程实例id:2501
    任务id:2505
    任务负责人:sam
    任务名称:创建出差申请
    

    实际执行sql:

    select distinct RES.* from ACT_RU_TASK RES inner join ACT_RE_PROCDEF D
    on RES.PROC_DEF_ID_ = D.ID_ WHERE RES.ASSIGNEE_ = 'sam' and D.KEY_ = 'MyEvection'
    order by RES.ID_ asc LIMIT 2147483647 OFFSET 0;
    
  • 完成个人待办任务

    @Test
    public void compleTask(){
        //获取taskService
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = processEngine.getTaskService();
        //根据任务id完成任务
        taskService.complete("2505");
    }
    

    任务完成后,流程则进入下一个节点;

    ACT_RU_TASK表中内容更新,而ACT_HI_TASKINST表与ACT_HI_ACTINST表中更新之前的任务节点的结束时间并新增目前流转到的节点信息…

  • 继续完成任务,直至流程结束,ACT_RU_xxx表中就没有内容了,ACT_HI_xxx中则记录了整个过程

流程操作

待续..