美文网首页
Activiti7 的基本介绍

Activiti7 的基本介绍

作者: Martain | 来源:发表于2021-01-19 09:34 被阅读0次

    前言

    最近接到上级的安排,要我为公司的某个系统设计一套工作流引擎。对于工作流引擎这一个主题,我查找了许多资料,在java方面用的比较多的是一个名叫Activiti的开源工作流引擎,通过与同事们交流之后,决定了使用该开源工作流引擎。在这段时间也是花了些时间来学习研究Activiti。网上的资料并不多,官方的文档是全英文的,而且更新的貌似不是很及时,所以准备写这个系列的文档来记录我的学习过程。

    官方地址

    我的写作水平还有待提高,可能很多人更愿意直接去看官方的一些教程,所以我先把地址放上!

    官方地址

    官方最新用户文档-V6.0.0

    码云镜像-activiti-7-developers-guide

    关于BPMN

    BPMN(Business Process Model AndNotation)- 业务流程模型和符号 是由BPMI(BusinessProcess Management Initiative)开发的一套标准的业务流程建模符号,使用BPMN提供的符号可以创建业务流程。2004年5月发布了BPMN1.0规范.BPMI于2005年9月并入OMG(The Object Management Group对象管理组织)组织OMG于2011年1月发布BPMN2.0的最终版本。

    Activiti 就是使用 BPMN 2.0 进行流程建模、流程执行管理,它包括很多的建模符号。

    image-20210116163216372

    可以使用这些符号来绘制流程图,例如下图:

    image-20210116165507302

    Activiti也是通过将这些流程图的BPMN文件部署到数据库中,然后启动相应的流程,来完成工作流的一个映射。这些节点可以指定一些参数、表达式、绑定事件或者绑定解析处理类,来实现对每个流程节点的处理。

    对于BPMN流程图的绘制方法这里就不做赘述,因为我也不是了解很多,网上有许多非常好的文章可供参考。

    Activiti 的架构

    引擎API是与Activiti交互的最常见方式。中心起点是ProcessEngine,可以按照配置部分中所述的多种方式创建 。从ProcessEngine,您可以获得包含工作流/ BPM方法的各种服务。ProcessEngine和服务对象是线程安全的。因此,您可以为整个服务器保留对其中之一的引用。

    api.services

    Activiti的工作流程是通过读取一个配置文件,然后得到一个工作流引擎实例,通过这个引擎可以获取多个不同模块的Service,然后就可以使用这些Service去完成相应的接口,比如部署会使用到RepositoryService,实例会用到RuntimeService等。(注意:FormServiceIdentityService已经在新版本中删除了)

    // 获取引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取Service
    RuntimeService runtimeService = processEngine.getRuntimeService();
    RepositoryService repositoryService = processEngine.getRepositoryService();
    TaskService taskService = processEngine.getTaskService();
    ManagementService managementService = processEngine.getManagementService();
    IdentityService identityService = processEngine.getIdentityService();
    HistoryService historyService = processEngine.getHistoryService();
    FormService formService = processEngine.getFormService();
    DynamicBpmnService dynamicBpmnService = processEngine.getDynamicBpmnService();
    

    Service总览

    Service名称 作用
    RepositoryService 资源管理服务
    RuntimeService 流程运行管理类
    TaskService 任务管理类
    HistoryService 历史管理类
    ManagerService 引擎管理类
    Activiti API activiti运行流程

    流程部署

    在使用Activiti进行流程管理之前,首先需要将建模工具绘制的业务流程图部署到数据库中,这个时候就需要使用RepositoryService,可以通过RepositoryService进行流程部署、查询流程定义、暂停或激活发布的流程定义等。官方教程

    部署流程

    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    RepositoryService repositoryService = processEngine.getRepositoryService();
    DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();
    Deployment deploy = deploymentBuilder
                                    .addClasspathResource("bpmn/stadiumapplication.bpmn")
                    .name("球场申请流程")
                    .deploy();
    

    部署方式

    ReposityService主要就是依靠调用DeploymentBuilder的接口来进行流程定义的部署的。DeploymentBuilder支持多种方式的部署。

    public interface DeploymentBuilder {
        // 文件流方式部署
      DeploymentBuilder addInputStream(String resourceName, InputStream inputStream);
      DeploymentBuilder addInputStream(String resourceName,Resource resource);
        // 资源文件方式部署
      DeploymentBuilder addClasspathResource(String resource);
        // 字符串内容部署,一般是bpmn的xml内容字符串部署
      DeploymentBuilder addString(String resourceName, String text);
        // 字节数组部署
      DeploymentBuilder addBytes(String resourceName, byte[] bytes);
      // Zip压缩包部署
      DeploymentBuilder addZipInputStream(ZipInputStream zipInputStream);
      // Bpmn模型部署,可动态生成BPMN model进行部署。
      DeploymentBuilder addBpmnModel(String resourceName, BpmnModel bpmnModel);
    
      DeploymentBuilder setProjectManifest(ProjectManifest projectManifest);
    
      DeploymentBuilder setEnforcedAppVersion(Integer enforcedAppVersion);
      
      /**
       *如果调用,则不会对bpmn2.0xsd进行XML模式验证。 
       *一般不推荐
       */
      DeploymentBuilder disableSchemaValidation();
    
      /**
       * 如果调用,则不会对流程定义进行验证,以确定流程定义在引擎上是可执行的。
       * 一般不推荐使用。
       */
      DeploymentBuilder disableBpmnValidation();
    
      /**
       * 为部署指定名字
       */
      DeploymentBuilder name(String name);
    
      /**
       * 为部署指定种类
       */
      DeploymentBuilder category(String category);
    
      /**
       * 为部署指定Key,该属性默认是bpmn的id
       */
      DeploymentBuilder key(String key);
    
      /**
       * 为部署指定租户ID,没有用到过。。。
       */
      DeploymentBuilder tenantId(String tenantId);
    
      /**
       * 如果已设置,则此部署将与以前的任何部署进行比较。这意味着每个(未生成的)资源都将与此部署提供的资源进行比较。
       */
      DeploymentBuilder enableDuplicateFiltering();
      
      /**
       * 设置激活此部署中包含的流程定义的日期。这意味着所有流程定义都将像往常一样部署,但它们将从在给定的激活日期之前开始。
       */
      DeploymentBuilder activateProcessDefinitionsOn(Date date);
      
      /**
       * 允许将影响部署的属性添加到实例中
       */
      DeploymentBuilder deploymentProperty(String propertyKey, Object propertyValue);
      
      /**
       * 将所有提供的源部署到Activiti引擎。
       */
      Deployment deploy();
    
    }
    

    涉及数据库表

    表名 作用
    ACT_RE_DEPLOYMENT 流程定义部署表:每部署一次增加一条记录
    ACT_RE_PROCDEF 流程定义表:部署每个新的流程都会在这张表上增加一条记录
    ACT_GE_BYTEARRAY 流程资源表:存储xml和png内容的表
    • ACT_GE_BYTEARRAY

      该表记录了流程的资源信息,包括bpmn文件的xml内容和png图片的二进制内容,RepositoryService也提供了相应的接口去获取这些资源。

      SELECT * FROM ACT_GE_BYTEARRAY;
      
      ID_ REV_ NAME_ DEPLOYMENT_ID_ BYTES_ GENERATED_
      2 1 bpmn/stadiumapplication.bpmn 1 (BLOB)4.43
    • ACT_RE_DEPLOYMENT

      SELECT * FROM ACT_RE_DEPLOYMENT;
      
      ID_ NAME_ CATEGORY_ KEY_ TENANT_ID_ DEPLOY_TIME_ ENGINE_VERSION_
      1 球场申请流程 2021-01-17 08:59:05
    • ACT_RE_PROCDEF

      SELECT * FROM ACT_RE_PROCDEF;
      
      ID_ REV_ CATEGORY_ NAME_ KEY_ VERSION_ DEPLOYMENT_ID_ RESOURCE_NAME_ DGRM_RESOURCE_NAME_ DESCRIPTION_ HAS_START_FORM_KEY_ HAS_GRAPHICAL_NOTATION_ SUSPENSION_STATE_ TENANT_ID_ ENGINE_VERSION_
      ballrepally:1:3 1 http://www.activiti.org/testm1574124674914 球场申请 ballrepally 1 1 bpmn/stadiumapplication.bpmn 0 1 1

      KEY_ 这个字段是用来唯一识别不同流程的关键字。

      ACT_RE_DEPLOYMENTACT_RE_PROCDEF是一对多的关系,即:一次部署可以部署多个流程定义,而只会在流程部署表(ACT_RE_DEPLOYMENT)生成一条记录。

      一般情况下建议一次部署只部署一个流程。

    查询流程信息

    • 查询流程部署信息

      // 获取流程部署查询器
      DeploymentQuery deploymentQuery =  repositoryService.createDeploymentQuery();
      // 查询列表。
      List<Deployment> deployments = deploymentQuery.list();
      
    • 查询流程定义信息

      // 获取流程定义查询器
      ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
      // 查询器构建查询条件,最终返回列表。
      List<ProcessDefinition> processDefinitionList = processDefinitionQuery
                                                                    .orderByProcessDefinitionVersion()
                                                                    .asc()
                                                                    .list();
      
    • 查询部署资源

      public interface RepositoryService {
        
        /**
         * 通过部署ID和资源名称获取资源流。 
         * @param deploymentId 部署ID
         * @param resourceName 资源名称 
         */
        InputStream getResourceAsStream(String deploymentId, String resourceName);
        
        /**
         * 检索给定部署的部署资源列表,按字母顺序排列。 
         * @param deploymentId 部署ID
         */
        List<String> getDeploymentResourceNames(String deploymentId);
        
        /**
         * 允许通过字节流访问已部署的流程模型,例如BPMN2.0XML文件。
         * @param processDefinitionId 流程定义ID
         */
        InputStream getProcessModel(String processDefinitionId);
        
        /**
         * 返回流程定义信息
         * @param processDefinitionId 流程定义ID
         */
        ProcessDefinition getProcessDefinition(String processDefinitionId);
         
      
        /**
         * 返回与具有提供的进程定义id的进程定义对应的BPMN 模型。
         * @param processDefinitionId 流程定义ID
         */
        BpmnModel getBpmnModel(String processDefinitionId);
        
      }
      

    挂起流程

    public interface RepositoryService {
        
       /**
       * 挂起给定id的流程定义。  
       */
      void suspendProcessDefinitionById(String processDefinitionId);
      
        /**
       * 挂起给定id的流程定义。  
       *
       * @param suspendProcessInstances 是否挂起流程实例
       *    如果为true,则提供的流程定义的所有流程实例也将挂起
       * @param suspensionDate 挂起日期
       *        进程定义将被挂起的日期。如果为null,进程定义将立即挂起。注意:作业执行器需要处于活动状态才能使用此命令!
       */
      void suspendProcessDefinitionById(String processDefinitionId, 
                                        boolean suspendProcessInstances, 
                                        Date suspensionDate);
      
      /**
       *  挂起给定流程定义Key的流程
       */
      void suspendProcessDefinitionByKey(String processDefinitionKey);
      
      /** 
       *  挂起给定流程定义Key的流程
       * @param suspendProcessInstances 是否挂起流程实例
       *    如果为true,则提供的流程定义的所有流程实例也将挂起
       * @param suspensionDate 挂起日期
       *        进程定义将被挂起的日期。如果为null,进程定义将立即挂起。注意:作业执行器需要处于活动状态才能使用此命令!
       */
      void suspendProcessDefinitionByKey(String processDefinitionKey, 
                                         boolean suspendProcessInstances,
                                         Date suspensionDate); 
      
      /**
       * 挂起给定流程定义Key和租户Id的流程。
       */
      void suspendProcessDefinitionByKey(String processDefinitionKey, String tenantId);
      
      ...
    }
    

    激活流程

    public interface RepositoryService {
        /**
       *  激活指定流程定义ID的流程
       */
      void activateProcessDefinitionById(String processDefinitionId); 
      
      /**
       * 激活指定流程定义ID的流程
       *
       * @param suspendProcessInstances 是否挂起流程实例
       *    如果为true,则提供的流程定义的所有流程实例也将激活
       * @param suspensionDate 挂起日期
       *        进程定义将被激活的日期。如果为null,进程定义将立即激活。注意:作业执行器需要处于挂起状态才能使用此命令!
       */
      void activateProcessDefinitionById(String processDefinitionId, 
                                         boolean activateProcessInstances, 
                                         Date activationDate);
      
      /**
       * 激活给定流程定义Key(BPMN图中的ID)的流程 
       */
      void activateProcessDefinitionByKey(String processDefinitionKey);
      
      /**
       * 激活指定流程定义Key的流程
       *
       * @param suspendProcessInstances 是否挂起流程实例
       *    如果为true,则提供的流程定义的所有流程实例也将激活
       * @param suspensionDate 挂起日期
       *        进程定义将被激活的日期。如果为null,进程定义将立即激活。注意:作业执行器需要处于挂起状态才能使用此命令!
       */
      void activateProcessDefinitionByKey(String processDefinitionKey, 
                                          boolean activateProcessInstances, 
                                          Date activationDate);
      
       /**
       *  激活给定流程定义Key和租户Id的流程
       */
      void activateProcessDefinitionByKey(String processDefinitionKey, String tenantId);
      
      ...
    }
    

    删除流程

    public interface RepositoryService {
     
      /**
       * 删除指定流程. 
       * @param deploymentId 流程部署ID
       */
      void deleteDeployment(String deploymentId);
      
      /**
       * 删除给定的部署和级联删除到流程实例、历史流程实例和作业。
       *
       * @param deploymentId 流程部署ID
       * @param cascade          是否级联删除
       */
      void deleteDeployment(String deploymentId, boolean cascade);
      
    }
    

    流程实例

    当我们将流程部署完成之后,先要使用他就得先开始一个流程实例。所谓流程实例,即比如我们部署了一个请假流程,小李的请假流程就是一个实例,小王的请假流程也是一个实例。所以我们的流程实例也是基于流程部署来实现的。

    流程实例的管理底层使用的是RuntimeService,而最新提供的ProcessRuntime对流程进行了二次封装,简便了api的调用。

    启动流程实例

      ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
      RuntimeService runtimeService = processEngine.getRuntimeService();
    
    public interface RuntimeService {
        
        /**
       * 启动先前创建的流程实例。 
       * @param createdProcessInstance 已经创建的流程实例 
       */
      ProcessInstance startCreatedProcessInstance(ProcessInstance createdProcessInstance, Map<String, Object> variables);
        
     /**
       * 开启指定流程定义Key的最新版本 
       * @param processDefinitionKey 流程定义的Key
       */
      ProcessInstance startProcessInstanceByKey(String processDefinitionKey);
    
      /**
       * 开启给定流程定义Key的最新版本,并指定业务流程Key   
       * @param processDefinitionKey 流程定义Key
       * @param businessKey 业务流程Key
       */
      ProcessInstance startProcessInstanceByKey(String processDefinitionKey, String businessKey);
    
      /**
       * 开启指定流程定义Key的最新版本
       *
       * @param processDefinitionKey 流程定义的Key
       * @param variables 流程的参数,比如uel参数 
       */
      ProcessInstance startProcessInstanceByKey(String processDefinitionKey, Map<String, Object> variables);
    
      /**
       * 开启给定流程定义Key的最新版本,并指定业务流程Key 
       * @param processDefinitionKey 流程定义Key
       * @param variables 参数
       * @param businessKey 业务Key
       */
      ProcessInstance startProcessInstanceByKey(String processDefinitionKey, String businessKey, Map<String, Object> variables);
    
      /**
       * 开启指定流程定义Id的最新版本. 
       * @param processDefinitionId 流程定义Id 
       */
      ProcessInstance startProcessInstanceById(String processDefinitionId);
    
      /**
       * 开启给定流程定义Id的最新版本,并指定业务流程Key
       * @param processDefinitionId 流程定义ID
       */
      ProcessInstance startProcessInstanceById(String processDefinitionId, String businessKey);
    
      /**
       * 开启给定流程定义Id的最新版本
       * @param processDefinitionId 流程定义Id
       * @param variables 参数
       */
      ProcessInstance startProcessInstanceById(String processDefinitionId, Map<String, Object> variables);
    
      /**
       * 开启给定流程定义Id的最新版本 
       * @param processDefinitionId 流程定义Id
       * @param variables 参数
       */
      ProcessInstance startProcessInstanceById(String processDefinitionId, String businessKey, Map<String, Object> variables);
    
    }
    

    涉及数据库表

    • ACT_RU_EXECTION

      流程实例执行表,记录当前流程实例的执行情况。流程实例执行,如果当前只有一个分支时,一个流程实例只有一条记录且执行表的主键id和流程实例id相同,如果当前有多个分支正在运行则该执行表中有多条记录,存在执行表的主键和流程实例id不相同的记录。

      不论当前有几个分支总会有一条记录的执行表的主键和流程实例id相同

      一个流程实例运行完成,此表中与流程实例相关的记录删除。

    • ACT_RU_TASK

      任务执行表,记录当前执行的任务。启动流程实例,流程当前执行到第一个任务结点,此表会插入一条记录表示当前任务的执行情况,如果任务完成则记录删除。

    • ACT_RU_IDENTITYLINK

      任务参与者,记录当前参与任务的用户或组。

    • ACT_HI_PROCINST

      流程实例历史表,流程实例启动,会在此表插入一条记录,流程实例运行完成记录也不会删除。

    • ACT_HI_TASKINST

      任务历史表,记录所有任务,开始一个任务,不仅在act_ru_task表插入记录,也会在历史任务表插入一条记录,任务历史表的主键就是任务id,任务完成此表记录不删除。

    • ACT_HI_ACTINST

      活动历史表,记录所有活动,活动包括任务,所以此表中不仅记录了任务,还记录了流程执行过程的其它活动,比如开始事件、结束事件。

      挂起流程实例

    /**
      * 挂起指定流程Id的流程实例 
      */
    void suspendProcessInstanceById(String processInstanceId);
    

    激活流程实例

    /**
      * 激活指定流程Id的流程实例 
      */
    void activateProcessInstanceById(String processInstanceId);
    

    删除流程实例

    /**
     * 删除实例 
     * @param processInstanceId 流程实例Id
     * @param deleteReason 删除原因
     */
    void deleteProcessInstance(String processInstanceId, String deleteReason);
    

    获取传入参数

    /**
     * 给定执行作用域(包括父作用域)中可见的所有变量。
     * @param executionId 启动的实例的ID
     */
    Map<String, Object> getVariables(String executionId);
    

    任务管理

    任务管理的接口是通过TaskService来实现的。而最新的是使用TaskRuntime接口来实现的,当然TaskRuntime底层也是通过TaskService来实现的。

    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    TaskService taskService = processEngine.getTaskService();
    

    获取我的任务

    // 获取任务查询器
    TaskQuery taskQuery = taskService.createTaskQuery();
    // 查询器获取列表
    List<Task> tasks = taskQuery.taskAssignee("you ID").list();
    

    拾取任务

    有的时候,某个任务节点可能没有直接指定责任人,但是指定了候选人列表或者候选组。这个时候你还是可以将这个任务查询出来的,但是需要主动拾取任务。

    TaskQuery taskQuery = taskService.createTaskQuery();
    Task task = taskQuery.processInstanceBusinessKey("businessKey").singleResult();
    // 拾取任务
    taskService.claim(task.getId(),"userId");
    

    解开任务

    如果拾取任务错了或者想将任务转给别人,可以调用解开任务的接口,其实也就是将责任人置空

    taskService.unclaim(String taskId);
    

    完成任务

    /**
      * 在任务成功执行时调用,并且所需的任务参数由最终用户给定。
      * @param taskId 任务ID
      * @param variables 参数对象
      */
    void complete(String taskId, Map<String, Object> variables);
    

    相关文章

      网友评论

          本文标题:Activiti7 的基本介绍

          本文链接:https://www.haomeiwen.com/subject/krhqzktx.html