Activiti使用中的数据变化

相信大家对流程引擎都不陌生,工作过一段时间的同学就会发现很多项目中都会通过流程引擎来解决审批问题,今天我们就来一起探究一下流程引擎在各个使用环节中的数据变化。

1 回顾流程引擎

首先我们先一起回顾一下流程引擎的诞生,在没有流程引擎的时代,大多数程序都是通过设置一个流转状态码来控制任务节点,通过用户角色控制其对任务的权限,然后审核通过与否也需要单独的字段来控制,当流程复杂时,需要复杂的代码去处理流程的变更。一旦流程出现变化,我们就需要去修改这段复杂的代码,来实现新的流程。当我们将新的逻辑发布,可能运行中的任务就会出现无法处理的情况。基于上述问题,流程引擎就此诞生。下面我们就以Activiti为例来探究一下流程引擎在使用中的数据变化。

2 Activiti使用中的数据变化

下面是Activiti工作流引擎的使用步骤,在每一个环节中,我们将会介绍基础的操作,以及数据变化。

2.1 初始化流程引擎

通过读取配置文件,构建流程引擎,初始化生成流程引擎需要的表,这些表的数据流转对我们理解流程引擎的原理起至关重要的作用

Activiti的所有数据库表都以ACT_ 开头,第二部分是说明表用途的两字符标示符,注意:MySQL数据库最好使用5.7及以上的版本

ACT_RE_ *: RE 代表 repository 。带有这个前缀的表包含"静态"信息,例如流程定义与流程资源(图片、规则等)。

ACT_RU_ *: RU 代表 runtime 。这些表存储运行时信息,例如流程实例(process instance)、用户任务(user task)、变量(variable)、作业(job)等。Activiti只在流程实例运行中保存运行时数据,并在流程实例结束时删除记录。保证运行时表小和快。

ACT_ID_ *: ID 代表 identity 。这些表包含身份信息,例如用户、组等。一般我们都不会直接使用它提供的身份表,而是以自己系统原有的身份信息表。

ACT_HI_ *: HI 代表 history 。这些表存储历史数据,例如已完成的流程实例、变量、任务等。

ACT_GE_ *: 通用数据。用于不同场景下

2.2 绘制BPMN流程图

绘制BPMN流程图,根据具体业务去设置流程

2.3 部署流程实例

将生成的流程信息,部署成为一个流程实例

ini 复制代码
// 1.获取ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 2.完成流程的部署操作 需要通过RepositoryService来完成
RepositoryService repositoryService = processEngine.getRepositoryService();
// 3.完成部署操作
Deployment deploy = repositoryService.createDeployment().addClasspathResource("flow/test.bpmn.xml").name("候选人").deploy(); // 是一个流程部署的行为 可以部署多个流程定义的
System.out.println(deploy.getId());
System.out.println(deploy.getName());

流程设计器设计流程后,会保存数据到act_re_model

部署流程后会生成以下表中的数据

2.4 发布流程

流程实例部署之后,就需要发布流程

ini 复制代码
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
// 发起流程 需要通过 runtimeService来实现
RuntimeService runtimeService = engine.getRuntimeService();
// 对流程变量做赋值操作
Map<String,Object> map = new HashMap<>();
map.put("assgin","上级领导");
// 通过流程定义ID来启动流程 返回的是流程实例对象
ProcessInstance processInstance = runtimeService.startProcessInstanceById("流程定义id","业务id",map);
System.out.println("processInstance.getId() = " + processInstance.getId());
System.out.println("processInstance.getDeploymentId() = " +
processInstance.getDeploymentId());
System.out.println("processInstance.getDescription() = " +
processInstance.getDescription());

在发布流程前就需要设置相关的流程变量,比如下一阶段审批人我们就可以用流程变量,变量设置为上级领导,我们就可以通过代码去查找当前用户的上级领导,设置到流程变量中,同时我们也可以使用候选人,或者候选人组,在业务中我们使用候选人组可以使用部门id,我们也可以使用流程变量,将候选人组设置为上级部门,这其实就是动态审批人,在使用候选人和候选人组的时候,支持任务拾取和任务归还,还有审批人交接等操作。

需要注意的是流程变量支持设置方法表达式

<math xmlns="http://www.w3.org/1998/Math/MathML"> p r i n t e r . p r i n t ( ) {printer.print()} </math>printer.print(){myBean.getAssignee()} ${myBean.addNewOrder('orderName')}

${myBean.doSomething(myVar, execution)}

与此同时设置审批人也可以使用监听器设置

typescript 复制代码
public class MyFirstListener implements TaskListener {
  /**
   * 监听器触发的回调方法
   * @param delegateTask
  */
  @Override
  public void notify(DelegateTask delegateTask) {
    System.out.println("---->自定义的监听器执行了");
    if(EVENTNAME_CREATE.equals(delegateTask.getEventName())){
      // 表示是Task的创建事件被触发了
      // 指定当前Task节点的处理人
      delegateTask.setAssignee("boge666");
    }
  }
}

发起流程成功后,在对应的 act_ru_task 中就有一条对应的待办记录,同时流程发起人,关联的候选人,审核组就会生成在act_ru_identitylink,设置的流程变量就会放在act_ru_variable中。

2.5 查询流程

流程发起之后我们就需要对流程进行查询

ini 复制代码
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
// 待办查询 执行中的任务处理通过 TaskService来实现
TaskService taskService = engine.getTaskService();
// Task 对象对应的其实就是 act_ru_task 这张表的记录
List<Task> list = taskService.createTaskQuery().taskAssignee("审批人id").list();
// 根据候选人查询审批任务 
// List<Task> list = taskService.createTaskQuery().taskCandidateUser("候选人id").list(); 
// 根据当前登录用户所属组查询
// List<Task> list = taskService.createTaskQuery().taskCandidateGroup("候选组id").list();
if(list != null && list.size() > 0){
  for (Task task : list) {
    System.out.println(task.getId());
    System.out.println(task.getName());
    System.out.println(task.getAssignee());
  }
} else {
  System.out.println("当前没有待办任务");
}

2.6 流程的拾取、归还、交接

流程的拾取、归还、交接

scss 复制代码
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = engine.getTaskService();
List<Task> list = taskService.createTaskQuery().taskCandidateUser("候选人id") .list();
if(list != null && list.size() > 0){
  for (Task task : list) {
    // 拾取 这个任务的审批权限 --> 变成了这个任务的审批人
    taskService.claim(task.getId(),"拾取人id");
    // 归还 操作的本质其实就是设置审批人为空
    taskService.unclaim(task.getId());
    // 交接 将审批人指定给其他人
    taskService.setAssignee(task.getId(),"交接人id");
  }
}

主要涉及到的就是act_ru_task中的assignee字段的数据变化

2.7 流程审批

流程的审批 审批时有多种走向需要结合网关和流程变量实现,网关出去的线条需要设置条件

流程引擎中的网关包括(排他网关、并行网关、包容网关,事件网关)

ini 复制代码
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = engine.getTaskService();
List<Task> list = taskService.createTaskQuery().taskAssignee("审批人id").list();
Map<String,Object> map = new HashMap<>();
// 绑定对应的请假天数
map.put("days",1);
for (Task task : list) {
  taskService.complete(task.getId(),map);
}

在并行网关中我们需要注意的是 执行实例 的概念。

主流程实例:流程启动就会维护的一条记录, ACT_RU_EXECUTION 中 parent_id_ 为null的记录

子流程实例: 流程的每一步操作。都会更新子流程实例,表示当前流程的执行进度。如果进入的是并行网关,is_concurrent_代表是否并行,is_active表示是否在执行,所有的都变成0,子实例才会消失,进入下一节点。

审核完成一个任务后会删除上一节点对应的 act_ru_task ,act_ru_identitylink,act_ru_variable数据,将数据保存到历史表中,同时将当前进入新节点的任务数据插入

2.8 流程中的事件

除此之外,流程引擎还支持事件功能,比如定时器,消息,错误,信号等事件,每一种事件又分为开始,中间,边界,结束事件。

定时任务的数据会写入到 act_ru_timer_job中,事件到了会跳转对应的任务节点

消息事件、信号事件会在act_ru_event_subscr中生成数据

2.9 流程的挂起与激活

挂起流程

ini 复制代码
// 创建 ProcessEngine 对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();
//根据一个流程实例的id挂起该流程实例
runtimeService.suspendProcessInstanceById("流程实例id");

激活流程

ini 复制代码
// 创建 ProcessEngine 对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();
//根据一个流程实例的id挂起该流程实例
runtimeService.activateProcessInstanceById("流程实例id");

act_ru_execution中SUSPENSION_STATE_中1为激活 2为挂起

2.10 流程的结束

审核完成后,可判断流程是否结束

java 复制代码
public boolean isProcessInstanceEnded(String processInstanceId) {
    // 创建 ProcessEngine 对象
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    
    // 根据流程实例 ID 查询流程实例
    ProcessInstance processInstance = processEngine.getRuntimeService()
            .createProcessInstanceQuery()
            .processInstanceId(processInstanceId)
            .singleResult();
    
    // 判断流程实例是否结束
    if (processInstance != null && processInstance.isEnded()) {
        return true;
    } else {
        return false;
    }
}

act_ru_execution中parent_id_为空的记录被删除代表流程结束

相关推荐
齐 飞1 分钟前
MongoDB笔记01-概念与安装
前端·数据库·笔记·后端·mongodb
LunarCod18 分钟前
WorkFlow源码剖析——Communicator之TCPServer(中)
后端·workflow·c/c++·网络框架·源码剖析·高性能高并发
码农派大星。1 小时前
Spring Boot 配置文件
java·spring boot·后端
杜杜的man1 小时前
【go从零单排】go中的结构体struct和method
开发语言·后端·golang
幼儿园老大*1 小时前
走进 Go 语言基础语法
开发语言·后端·学习·golang·go
llllinuuu2 小时前
Go语言结构体、方法与接口
开发语言·后端·golang
cookies_s_s2 小时前
Golang--协程和管道
开发语言·后端·golang
为什么这亚子2 小时前
九、Go语言快速入门之map
运维·开发语言·后端·算法·云原生·golang·云计算
想进大厂的小王2 小时前
项目架构介绍以及Spring cloud、redis、mq 等组件的基本认识
redis·分布式·后端·spring cloud·微服务·架构
customer082 小时前
【开源免费】基于SpringBoot+Vue.JS医院管理系统(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·开源·intellij-idea