zoukankan      html  css  js  c++  java
  • Activiti(工作流-2)执行过程解析

    (转载https://blog.csdn.net/lp2388163/article/details/98206543?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2allsobaiduend~default-1-98206543.nonecase&utm_term=activiti%20%E6%89%A7%E8%A1%8C%E9%A1%BA%E5%BA%8F&spm=1000.2123.3001.4430)

    1.activiti工作流执行过程解析

    [执行过程interceptor、cmd、listener、handler]

    1.activiti核心对象解释:

    ProcessEngine:

    ProcessEngines.getDefaultProcessEngine()会在第一次调用时 初始化并创建一个流程引擎,以后再调用就会返回相同的流程引擎。 使用对应的方法可以创建和关闭所有流程引擎:ProcessEngines.init()和ProcessEngines.destroy()。

    RepositoryService:

    可能是使用Activiti引擎时最先接触的服务。 它提供了管理和控制发布包和流程定义的操作。它包含了一个流程每个环节的结构和行为。可以自由选择把任意资源包含到发布包中。 既可以把一个单独的BPMN 2.0 xml文件放到发布包里,也可以把整个流程和相关资源都放在一起。发布一个发布包,意味着把它上传到引擎中,所有流程都会在保存进数据库之前分析解析好。

    TaskService:

    任务是由系统中真实人员执行的,所有与任务有关的功能都包含在TaskService中:

    查询分配给用户或组的任务。

    创建独立运行任务。这些任务与流程实例无关。

    手工设置任务的执行者,或者这些用户通过何种方式与任务关联。

    认领并完成一个任务。认领意味着一个人期望成为任务的执行者, 即这个用户会完成任务。完成意味着“做这个任务要求的事情”。 通常来说会有很多种处理形式。

    IdentityService:

    它可以管理(创建,更新,删除,查询...)群组和用户。

    HistoryService:

    提供了Activiti引擎手机的所有历史数据。 在执行流程时,引擎会保存很多数据(根据配置),比如流程实例启动时间,任务的参与者, 完成任务的时间,每个流程实例的执行路径,等等。 这个服务主要通过查询功能来获得这些数据。

    RuntimeService:

    执行管理,包括启动,推进,删除流程实例等操作,在流程运行时对流程实例进行管理与控制。

    2.表名前缀解释:

    ACT_GE_*: “GE”代表“General”(通用),用在各种情况下。

    ACT_HI_*: “HI”代表“History”(历史),这些表中保存的都是历史数据,比如执行过的流程实例、变量、任务,等等。

    指定保存历史记录级别:

       Ønone: 不保存任何历史记录,可以提高系统性能;
    
       Øactivity:保存所有的流程实例、任务、活动信息;
    
       Øaudit:也是Activiti的默认级别,保存所有的流程实例、任务、活动、表单属性;
    
       Øfull:最完整的历史记录,除了包含audit级别的信息之外还能保存详细,例如:流程变量。
    

    ACT_ID_*: “ID”代表“Identity”(身份),这些表中保存的都是身份信息,如用户和组以及两者之间的关系。如果Activiti被集成在某一系统当中的话,这些表可以不用,可以直接使用现有系统中的用户或组信息;

    ACT_RE_*: “RE”代表“Repository”(仓库),这些表中保存一些‘静态’信息,如流程定义和流程资源(如图片、规则等);

    ACT_RU_*: “RU”代表“Runtime”(运行时),这些表中保存一些流程实例、用户任务、变量等的运行时数据。Activiti只保存流程实例在执行过程中的运行时数据,并且当流程结束后会立即移除这些数据,这是为了保证运行时表尽量的小并运行的足够快;

    3.activiti异常声明:

    ActivitiWrongDbException:当Activiti引擎发现数据库版本号和引擎版本号不一致时抛出。

    ActivitiOptimisticLockingException:对同一数据进行并发方法并出现乐观锁时抛出。

    ActivitiClassLoadingException:当无法找到需要加载的类或在加载类时出现了错误(比如,JavaDelegate,TaskListener等。

    ActivitiObjectNotFoundException:当请求或操作的对应不存在时抛出。

    ActivitiIllegalArgumentException:这个异常表示调用Activiti API时传入了一个非法的参数,可能是引擎配置中的非法值,或提供了一个非法制,或流程定义中使用的非法值。

    ActivitiTaskAlreadyClaimedException:当任务已经被认领了,再调用taskService.claim(...)就会抛出。

    4.Demo流程图:

    Demo代码演示:

    // 创建流程引擎对象

    private ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

    // 流程定义

    processEngine.getRepositoryService()

        .createDeployment()
    
        .name("test")
    
        .addClasspathResource("activitiTest.bpmn")
    
        .deploy();
    

    // 流程启动

    ProcessInstance pi = processEngine.getRuntimeService()

        .startProcessInstanceByKey("activitiTest");
    

    System.out.println("pId: " + pi.getId() + ", pName: " + pi.getName());

    // 查询指定代理人的任务,进行执行
    TaskService taskService = processEngine.getTaskService();

    // 根据assignee查询员工任务

    List tasks = taskService.createTaskQuery().taskAssignee("员工").list();

    for (Task task : tasks) {

    System.out.println("taskId: " + task.getId() + ", taskAssignee: " + task.getAssignee());
    
    // 添加员工基本信息
    

    taskService.setVariable(task.getId(), "请假人", "原野" + task.getId());

    taskService.setVariable(task.getId(), "请假时长", 7);
    
    taskService.setVariable(task.getId(), "日期", new Date());
    
    // 提交申请(执行任务)
    

    taskService.complete(task.getId());

    }

    /提交申请后,任务流向下一个节点/

    Task task1 = taskService.createTaskQuery().taskAssignee("上司").singleResult();

    System.out.println("taskId: " + task1.getId() + ", taskAssignee: " + task1.getAssignee() + ", taskName: " + task1.getName() + ", taskTime: " + task1.getCreateTime());

    // 上司查看员工基本信息

    String name = (String) taskService.getVariable(task1.getId(), "请假人");

    Integer time = (Integer) taskService.getVariable(task1.getId(), "请假时长");

    Date date = (Date) taskService.getVariable(task1.getId(), "日期");

    System.out.println("name: " + name + ", time: " + time + ", date: " + date);

    // 上司审批完成

    taskService.complete(task1.getId());
    // 流程走到结束事件,流程结束!

    以上是一个简单的流程Demo,演示一个员工申请请假,上司审批的过程。

    首先需要定义bpmn流程图,然后针对该流程图(xml)的操作是:

    定义流程 -> 启动流程 ->执行流程步骤 -> 结束

    在这个过程中,先通过RepositoryService对象对流程进行定义,流程的xml信息等会被加载到数据库表中,并创建流程解析和部署的数据。然后启动流程通过RuntimeService对象指定xml的 id启动,对应流程解析表的key。根据定义流程的信息创建对应的流程实例,流程任务。最后通过TaskService对象查询任务执行任务等,执行完成后流程结束。

    1. 流程发布

    简述:

    首先创建一个ProcessEngine的流程引擎对象,该对象创建过程中会检查数据库中是否存在了activiti需要的基础表,不存在则创建。

    根据RepositoryService创建部署对象,通过addClasspathResource().deploy对指定的bpmn文件进行加载,在数据库中保存这些基本信息后,流程发布完成,数据库中存储了xml和流程发布的基本信息后,可以进行流程启动。

    细节:

    在创建流程引擎的过程中,会首先判断数据库中是否存在了基本的表结构,如果没有就会初始化表结构(创建28张表/activiti6.0之前版本是23张)

    之后往ACT_GE_PROPERTY(系统相关属性表)插入四条数据,保存工作流引擎的基本信息。如果原本的表结构以及系统相关属性纪录已经存在,则不做上述操作。

    创建流程引擎后的ACT_GE_PROPERTY,字段分别是属性名,属性值,版本号

    在定义流程的过程中,ACT_GE_PROPERTY表中的next.dbid的value,作为ACT_RE_DEPLOYMENT(流程部署信息表)的主键id,生成一条流程部署纪录。

    同时往ACT_GE_BYTEARRAY(流程资源表)和ACT_RE_PROCDEF(流程解析表)插入一条纪录,这两条纪录都关联部署信息表的id。

    然后对ACT_GE_PROPERTY表纪录修改,修改后的next.dbid作为下一个流程部署信息纪录的主键。

    如果对同一个流程部署两次的话,ACT_GE_BYTEARRAY(流程资源表),ACT_RE_PROCDEF(流程解析表),ACT_GE_PROPERTY(流程部署表)都会相应的增加一条纪录。在ACT_RE_PROCDEF表中有VERSION字段,在根据key启动流程的时候是基于VERSION最大的记录启动。

    删除一个流程定义:

    因为指定了级联, ACT_RE_DEPLOYMENT表id为10001这条纪录被删除,ACT_GE_BYTEARRAY,ACT_RE_PROCDEF关联这条纪录的数据也被删除。

    1. 流程的启动

    简述:

    因为在上一步已经发布了流程,那么在这里就是针对发布的流程进行一个启动,发布的流程xml信息保存在了数据库中,这里通过RuntimeService对象的startProcessInstanceByKey()来启动流程(也可以通过其他方法),参数为xml的的id,启动流程后该流程实例被生成,可以针对这个流程实例进行任务的执行,驳回,查看任务,分派任务等操作。

    细节:

    启动流程一般是根据startProcessInstanceByKey()来启动流程,也就是ACT_RE_PROCDEF(流程解析表)的Key_字段,XML文件中的id。也可以根据startProcessInstanceById()等来启动(流程解析表主键id)。

    整个启动对数据库表的操作过程为:

    1. 根据startProcessInstanceByKey()拿Key_查询流程解析表,获得流程解析表中的一条数据,如果存在重复Key_数据,取Max(版本号)的一条。

    2. 因为ACT_RE_PROCDEF(流程解析表)关联了ACT_RE_DEPLOYMENT(部署信息表),而ACT_GE_BYTEARRAY(流程资源表)又关联了ACT_RE_DEPLOYMENT,所以在流程启动时就拿到了发布流程的所有信息。

    3. 开始启动流程,往ACT_HI_PROCINST(历史流程实例)创建历史实例记录,ACT_HI_ACTINST(历史节点)创建历史节点记录。ACT_HI_TASKINST(历史任务表),ACT_HI_IDENTITYLINK(历史流程人员表)添加纪录(如果存在)

    历史实例:

    历史节点:

    历史任务:

    历史流程人员:

    1. 在ACT_RU_EXECUTION(运行时流程实例表)创建流程实例记录,如果该节点存在任务则在ACT_RU_TASK(运行时任务表)创建任务记录,ACT_RU_IDENTITYLINK(运行流程人员表)创建流程中任务办理人员记录。如果进行了setVariables()则在ACT_HI_VARINST(历史变量表),ACT_RU_VARIABLE(运行变量表)添加变量信息

    运行实例:

    运行任务:

    运行流程人员:

    历史变量以及运行时变量:

    其中所有历史纪录表关联了实例表,而实例表关联流程解析表id

    运行时表围绕实例表和解析表关联,运行实例表关联解析表id

    1. 任务管理

    简述:

    在流程启动后,流程走向了用户任务节点,那么该节点就会有一条在ACT_RU_TASK(运行任务)中的代办任务记录,通过创建查询对象,根据assignee查询表中ASSIGNEE_为员工的记录,查到这些任务后,通过setVarable往ACT_RU_VARIABLE,ACT_HI_VARINST添加变量信息,然后通过complete()完成指定的任务,流程流向下一个节点。下一个节点同上一样,查询自己的任务,是否完成(批准),查看参数变量。

    细节:

    首先会根据api去ACT_RU_TASK(运行任务表)查询指定的任务,这里是根据taskAssignee(),也就是指定人查询,查询的条件为运行任务表中的ASSIGNEE_字段,查到的任务返回后,得到taskId。

    setVariable(),意味着往ACT_HI_VARINST,ACT_RU_VARIABLE变量表中添加变量信息,该表关联流程实例表,运行时变量表在执行完后会删除,历史纪录会保存下来。

    执行complete(taskId)方法时,指定的运行时任务完成,那么ACT_RU_TASK表中删除该条任务记录,历史纪录表中update结束时间,流程流向下一个节点,如果下一个节点是任务节点,那么又会创建新的任务,以及历史任务。

  • 相关阅读:
    [MyBatis]最简MyBatis工程
    eclipse中如何删除已经添加到 Web App Libraries 中引用的jar包
    day48_项目管理学习笔记
    项目流程之失败的案例
    项目流程之婚礼流程
    day47_Maven学习笔记
    快还要更快,让PHP 7 运行更加神速
    Linux服务器时间同步
    Win10系统开启Linux Bash命令行
    红帽RHOP 8 发布一条龙方案
  • 原文地址:https://www.cnblogs.com/jnnleo/p/13884931.html
Copyright © 2011-2022 走看看