乐趣区

关于springboot:Flowable-设置流程变量的四种方式

@[toc]
在之前的文章中,松哥也有和小伙伴们应用过流程变量,然而没有和大家零碎的梳理过流程变量的具体玩法以及它对应的数据表详情,明天咱们就来看看 Flowable 中流程变量的具体玩法。

1. 为什么须要流程变量

首先咱们来看看为什么须要流程变量。

举一个简略的例子,假如咱们有如下一个流程:

这是一个销假流程,那么谁销假、请几天、起始工夫、销假理由等等,这些都须要阐明,不然领导审批的根据是啥?那么如何传递这些数据,咱们就须要流程变量。

2. 流程变量的分类

整体上来说,目前流程变量能够分为三种类型:

  1. 全局流程变量:在整个流程执行期间,这个流程变量都是无效的。
  2. 本地流程变量:这个只针对流程中某一个具体的 Task(工作)无效,这个工作执行结束后,这个流程变量就生效了。
  3. 长期流程变量:顾名思义就是长期的,这个不会存入到数据库中。

在接下来的内容中,我会跟大家挨个介绍这些流程变量的用法。

3. 全局流程变量

假如咱们就是下面这个销假流程,咱们一起来看下流程变量的设置和获取。

3.1 启动时设置

第一种形式,就是咱们能够在流程启动的时候,设置流程变量,如下:

@Test
void test01() {Map<String, Object> variables = new HashMap<>();
    variables.put("days", 10);
    variables.put("reason", "劳动一下");
    variables.put("startTime", new Date());
    ProcessInstance pi = runtimeService.startProcessInstanceByKey("demo01", variables);
    logger.info("id:{},activityId:{}", pi.getId(), pi.getActivityId());
}

咱们能够在启动的时候为流程设置变量,小伙伴们留神到,流程变量的 value 也能够是一个对象(不过这个对象要可能序列化,即实现了 Serializable 接口),而后在启动的时候传入这个变量即可。

咱们在流程启动日志中搜寻 劳动一下 四个字,能够找到和流程变量相干的 SQL,一共有两条,如下:

insert into ACT_HI_VARINST (ID_, PROC_INST_ID_, EXECUTION_ID_, TASK_ID_, NAME_, REV_, VAR_TYPE_, SCOPE_ID_, SUB_SCOPE_ID_, SCOPE_TYPE_, BYTEARRAY_ID_, DOUBLE_, LONG_ , TEXT_, TEXT2_, CREATE_TIME_, LAST_UPDATED_TIME_) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) , (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) , (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

INSERT INTO ACT_RU_VARIABLE (ID_, REV_, TYPE_, NAME_, PROC_INST_ID_, EXECUTION_ID_, TASK_ID_, SCOPE_ID_, SUB_SCOPE_ID_, SCOPE_TYPE_, BYTEARRAY_ID_, DOUBLE_, LONG_ , TEXT_, TEXT2_) VALUES (?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) , (?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) , (?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

从标名称上大略就能看进去,ACT_HI_VARINST 是存储流程执行的历史信息的,ACT_RU_VARIABLE 则是保留流程运行时候的信息的。

咱们关上 ACT_RU_VARIABLE 表来看一下:

从表中咱们能够看到,每一个流程变量都有对应的流程实例 ID,这就阐明这些流程变量是属于某一个流程实例的,所以咱们能够依照如下形式来查问流程变量:

@Test
void test01() {List<Execution> list = runtimeService.createExecutionQuery().list();
    for (Execution execution : list) {Object reason = runtimeService.getVariable(execution.getId(), "reason");
        logger.info("reason:{}", reason);
    }
}

对应的查问 SQL 如下:

: ==>  Preparing: select * from ACT_RU_VARIABLE WHERE EXECUTION_ID_ = ? AND TASK_ID_ is null AND NAME_ = ?
: ==> Parameters: 6fdd2007-4c3a-11ed-aa7e-acde48001122(String), reason(String)
: <==      Total: 1

能够看到,这个就是去 ACT_RU_VARIABLE 表中进行查问,查问条件中蕴含了变量的名称。

当然,咱们也能够间接查问某一个流程的所有变量,如下:

@Test
void test02() {List<Execution> list = runtimeService.createExecutionQuery().list();
    for (Execution execution : list) {Map<String,Object> variables = runtimeService.getVariables(execution.getId());
        logger.info("variables:{}", variables);
    }
}

这个对应的查问 SQL 如下:

 : ==>  Preparing: select * from ACT_RU_VARIABLE WHERE EXECUTION_ID_ = ? AND TASK_ID_ is null
 : ==> Parameters: 6fdd2007-4c3a-11ed-aa7e-acde48001122(String)
 : <==      Total: 3

能够看到,这个跟下面的那个差不多,只不过少了 NAME_ 这个条件。

3.2 通过 Task 设置

咱们也能够在流程启动胜利之后,再去设置流程变量,步骤如下:

首先启动一个流程:

@Test
void test01() {ProcessInstance pi = runtimeService.startProcessInstanceByKey("demo01");
    logger.info("id:{},activityId:{}", pi.getId(), pi.getActivityId());
}

而后设置流程变量:

@Test
void test03() {Task task = taskService.createTaskQuery().singleResult();
    taskService.setVariable(task.getId(), "days", 10);
    Map<String, Object> variables = new HashMap<>();
    variables.put("reason", "劳动一下");
    variables.put("startTime", new Date());
    taskService.setVariables(task.getId(),variables);
}

查问到某一个 Task,而后设置流程变量,下面这段代码和小伙伴们演示了两种设置形式:

  • 一一设置
  • 间接设置一个 Map

下面这个设置流程变量的形式,实质上还是往 ACT_HI_VARINSTACT_RU_VARIABLE 表中插入数据。具体的 SQL 也和后面的一样,我就不贴出来了。

3.3 实现工作时设置

也能够在实现一个工作的时候设置流程变量,如下:

@Test
void test04() {Task task = taskService.createTaskQuery().singleResult();
    Map<String, Object> variables = new HashMap<>();
    variables.put("reason", "劳动一下");
    variables.put("startTime", new Date());
    variables.put("days", 10);
    taskService.complete(task.getId(),variables);
}

底层波及到的 SQL 都跟后面一样,我就不赘述了。

3.4 通过流程设置

因为是全局流程变量,所以咱们也能够通过 RuntimeService 来进行设置,如下:

@Test
void test05() {Execution execution = runtimeService.createExecutionQuery().singleResult();
    runtimeService.setVariable(execution.getId(), "days", 10);
    Map<String, Object> variables = new HashMap<>();
    variables.put("reason", "劳动一下");
    variables.put("startTime", new Date());
    runtimeService.setVariables(execution.getId(), variables);
}

好啦,一共就是这四种形式。

4. 本地流程变量

第三大节咱们说的全局流程变量是和某一个具体的流程绑定的,而本地流程变量则不同,本地流程变量和某一个 Task 绑定。

4.1 通过 Task 设置

假如咱们启动流程之后,通过 Task 来设置一个本地流程变量,形式如下:

@Test
void test03() {Task task = taskService.createTaskQuery().singleResult();
    taskService.setVariableLocal(task.getId(), "days", 10);
    Map<String, Object> variables = new HashMap<>();
    variables.put("reason", "劳动一下");
    variables.put("startTime", new Date());
    taskService.setVariables(task.getId(),variables);
}

下面这段代码中,我设置了一个本地变量,两个全局变量,设置实现后,咱们去 ACT_RU_VARIABLE 表中来查看一下具体的成果。

大家看到,因为 days 是本地变量,所以它的 TASK_ID_ 有值,这个好了解,阐明 days 这个变量和这个具体的 Task 是无关的。

此时如果咱们实现这个 Task,代码如下:

@Test
void test06() {Task task = taskService.createTaskQuery().singleResult();
    taskService.complete(task.getId());
}

实现之后,再来查看 ACT_RU_VARIABLE 表,如下:

咱们发现本地变量 days 曾经没有了。因为上一个 Task 都曾经执行结束了,这个时候如果还是依照第三大节介绍的形式去查问变量,就查不到 days 了。此时如果须要查问到已经的 days 变量,得去历史表中查问了,形式如下:

@Test
void test07() {ProcessInstance pi = runtimeService.createProcessInstanceQuery().singleResult();
    List<HistoricVariableInstance> list = historyService.createHistoricVariableInstanceQuery().processInstanceId(pi.getId()).list();
    for (HistoricVariableInstance hvi : list) {logger.info("name:{},type:{},value:{}", hvi.getVariableName(), hvi.getVariableTypeName(), hvi.getValue());
    }
}

这是流程本地变量的特点,当然相干的办法还有好几个,这里列出来给小伙伴们参考:

  • org.flowable.engine.TaskService#complete(java.lang.String, java.util.Map<java.lang.String,java.lang.Object>, boolean):在实现一个 Task 的时候,如果传递了变量,则能够通过第三个参数来管制这个变量是全局的还是本地的,true 示意这个变量是本地的。
  • org.flowable.engine.RuntimeService#setVariableLocal:为某一个执行实例设置本地变量。
  • org.flowable.engine.RuntimeService#setVariablesLocal:同上,批量设置。

好啦,这就是本地流程变量。

5. 长期流程变量

长期流程变量是不存数据库的,一般来说咱们能够在启动流程或者实现工作的时候应用,用法如下:

@Test
void test21() {Map<String, Object> variables = new HashMap<>();
    variables.put("reason", "劳动一下");
    variables.put("startTime", new Date());
    ProcessInstance pi = runtimeService
            .createProcessInstanceBuilder()
            .transientVariable("days", 10)
            .transientVariables(variables)
            .processDefinitionKey("demo01")
            .start();
    logger.info("id:{},activityId:{}", pi.getId(), pi.getActivityId());
}

下面这段代码波及到的流程变量就是长期流程变量,它是不会存入到数据库中的。

也能够在实现一个工作的时候设置长期变量,如下:

@Test
void test22() {Task task = taskService.createTaskQuery().singleResult();
    Map<String, Object> transientVariables = new HashMap<>();
    transientVariables.put("days", 10);
    taskService.complete(task.getId(), null, transientVariables);
}

这个长期变量也是不会存入到数据库中的。

好啦,对于流程变量,明天就和小伙伴们先说这么多~

退出移动版