流程变量 Variables
在 Activiti 中,流程变量(Process Variables)是流程实例或任务级别的数据,可以在流程的不同阶段设置和访问。以下是几种设置流程变量的方式及其区别、优先级和覆盖规则:
1. 设置流程变量的方式
1.1 启动流程时设置流程变量
使用 runtimeService.startProcessInstanceByKey
或 runtimeService.startProcessInstanceById
启动流程时,可以传入流程变量。
Map<String, Object> variables = new HashMap<>();
variables.put("key1", "value1");
variables.put("key2", 100);
runtimeService.startProcessInstanceByKey("myProcess", businessKey, variables);
- 作用范围:这些变量属于流程实例级别,可以在整个流程实例中访问。
- 优先级:启动时设置的变量是初始变量,优先级最低(可以被后续设置的变量覆盖)。
1.2 办理任务时设置流程变量
使用 taskService.complete(taskId, variables)
完成任务时,可以传入流程变量。
Map<String, Object> variables = new HashMap<>();
variables.put("key2", 200);
variables.put("key3", true);
taskService.complete(taskId, variables);
- 作用范围:这些变量属于流程实例级别,可以在整个流程实例中访问。
- 优先级:完成任务时设置的变量会覆盖之前同名的流程变量。
taskService.setVariable
设置任务变量
1.3 使用 使用 taskService.setVariable
可以在任务执行过程中设置流程变量。
taskService.setVariable(taskId, "key4", "value4");
- 作用范围:这些变量属于流程实例级别,可以在整个流程实例中访问。
- 优先级:与完成任务时设置的变量相同,会覆盖之前同名的流程变量。
taskService.setVariableLocal
设置任务本地变量
1.4 使用 使用 taskService.setVariableLocal
可以设置任务本地变量。
taskService.setVariableLocal(taskId, "key5", "value5");
- 作用范围:这些变量属于任务级别,只能在当前任务中访问。
- 优先级:任务本地变量不会覆盖流程实例级别的变量,两者是独立的。
2. 变量优先级和覆盖规则
2.1 流程实例变量 vs 任务本地变量
- 流程实例变量:在整个流程实例中共享,优先级较低(可以被后续设置的流程实例变量覆盖)。
- 任务本地变量:仅在当前任务中有效,优先级较高(不会覆盖流程实例变量,也不会被流程实例变量覆盖)。
2.2 变量覆盖规则
- 如果使用
taskService.complete(taskId, variables)
或taskService.setVariable
设置变量,会覆盖同名的流程实例变量。 - 如果使用
taskService.setVariableLocal
设置变量,不会影响流程实例变量,任务本地变量仅在当前任务中有效。
2.3 变量查询规则
- 使用
runtimeService.getVariable
查询变量时,只能查询流程实例变量。 - 使用
taskService.getVariable
查询变量时,会先查询任务本地变量,如果不存在,则查询流程实例变量。 - 使用
taskService.getVariableLocal
查询变量时,只能查询任务本地变量。
3. 示例代码
以下是一个完整的示例,展示不同方式设置变量的行为:
// 启动流程时设置变量
Map<String, Object> startVariables = new HashMap<>();
startVariables.put("key1", "value1");
startVariables.put("key2", 100);
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("myProcess", businessKey, startVariables);
// 查询流程实例变量
String value1 = (String) runtimeService.getVariable(processInstance.getId(), "key1"); // "value1"
Integer value2 = (Integer) runtimeService.getVariable(processInstance.getId(), "key2"); // 100
// 办理任务时设置变量
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
Map<String, Object> completeVariables = new HashMap<>();
completeVariables.put("key2", 200);
completeVariables.put("key3", true);
taskService.complete(task.getId(), completeVariables);
// 查询更新后的流程实例变量
value2 = (Integer) runtimeService.getVariable(processInstance.getId(), "key2"); // 200
Boolean value3 = (Boolean) runtimeService.getVariable(processInstance.getId(), "key3"); // true
// 使用 setVariable 设置变量
Task newTask = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
taskService.setVariable(newTask.getId(), "key4", "value4");
// 查询更新后的流程实例变量
String value4 = (String) runtimeService.getVariable(processInstance.getId(), "key4"); // "value4"
// 使用 setVariableLocal 设置任务本地变量
taskService.setVariableLocal(newTask.getId(), "key5", "value5");
// 查询任务本地变量
String value5 = (String) taskService.getVariableLocal(newTask.getId(), "key5"); // "value5"
String value5Global = (String) runtimeService.getVariable(processInstance.getId(), "key5"); // null
4. 总结
设置方式 | 作用范围 | 优先级 | 覆盖规则 |
---|---|---|---|
runtimeService.startProcessInstanceByKey | 流程实例级别 | 低 | 可以被后续设置的流程实例变量覆盖 |
taskService.complete(taskId, variables) | 流程实例级别 | 高 | 覆盖同名的流程实例变量 |
taskService.setVariable | 流程实例级别 | 高 | 覆盖同名的流程实例变量 |
taskService.setVariableLocal | 任务级别 | 独立 | 不影响流程实例变量 |
- 流程实例变量:在整个流程中共享,优先级较低。
- 任务本地变量:仅在当前任务中有效,优先级较高,且独立于流程实例变量。
- 覆盖规则:后设置的变量会覆盖同名的流程实例变量,任务本地变量不会覆盖流程实例变量。
在 Activiti 中,taskService.complete(taskId, variables)
和 taskService.setVariable(taskId, "flag", 0)
都是设置流程变量的方式,但它们的行为和优先级有所不同。以下是对它们的详细解释:
taskService.complete(taskId, variables)
1. - 作用:完成任务并设置流程变量。
- 行为:
- 完成任务后,流程会继续执行到下一个节点。
- 传入的变量会作为流程实例变量保存。
- 优先级:
- 这些变量会在任务完成时设置,覆盖之前同名的流程实例变量。
- 如果任务完成后流程进入下一个节点,这些变量会立即生效。
taskService.setVariable(taskId, "flag", 0)
2. - 作用:在当前任务执行过程中设置流程变量。
- 行为:
- 设置的变量会立即生效,但不会触发任务完成或流程流转。
- 这些变量会覆盖之前同名的流程实例变量。
- 优先级:
- 设置的变量会立即覆盖同名的流程实例变量。
3. 优先级和覆盖规则
- 优先级:
taskService.setVariable(taskId, "flag", 0)
的优先级高于taskService.complete(taskId, variables)
。- 这是因为
setVariable
是立即生效的,而complete
是在任务完成时才生效。
- 覆盖规则:
- 如果在调用
taskService.complete(taskId, variables)
之前调用了taskService.setVariable(taskId, "flag", 0)
,那么setVariable
设置的变量会立即覆盖同名的流程实例变量。 - 如果在
complete
中传入了同名的变量,那么complete
中的变量会覆盖setVariable
设置的变量。
- 如果在调用
4. 示例代码
以下是一个示例,展示两者的优先级和覆盖行为:
// 启动流程
Map<String, Object> startVariables = new HashMap<>();
startVariables.put("flag", 1);
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("myProcess", startVariables);
// 查询任务
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
// 使用 setVariable 设置变量
taskService.setVariable(task.getId(), "flag", 0);
// 查询变量
Integer flagValue = (Integer) runtimeService.getVariable(processInstance.getId(), "flag");
System.out.println("After setVariable, flag = " + flagValue); // 输出: 0
// 使用 complete 完成任务并设置变量
Map<String, Object> completeVariables = new HashMap<>();
completeVariables.put("flag", 2);
taskService.complete(task.getId(), completeVariables);
// 查询变量
flagValue = (Integer) runtimeService.getVariable(processInstance.getId(), "flag");
System.out.println("After complete, flag = " + flagValue); // 输出: 2
5. 总结
操作 | 行为 | 优先级 | 覆盖规则 |
---|---|---|---|
taskService.setVariable(taskId, "flag", 0) | 立即设置流程变量,覆盖同名变量。 | 高 | 立即覆盖同名变量。 |
taskService.complete(taskId, variables) | 完成任务并设置流程变量,变量在任务完成时生效。 | 低 | 覆盖 setVariable 设置的变量。 |
- 优先级:
setVariable
的优先级高于complete
。 - 覆盖规则:
setVariable
会立即覆盖同名变量。complete
会在任务完成时覆盖setVariable
设置的变量。
因此,如果你在任务完成前调用了 setVariable
,那么 setVariable
的值会立即生效;如果在 complete
中传入了同名变量,那么 complete
的值会覆盖 setVariable
的值。