**流程变量 (Process Variables)。**这是 Flowable (乃至所有BPMN引擎) 中最基本、最重要的概念之一。掌握了它,你就掌握了驱动流程运转的“燃料”。
简单来说,流程变量是附加到单个流程实例上的数据。可以将其想象成一个“数据背包”,这个背包会从流程开始的那一刻起,一直跟随着这个流程实例,直到它结束。流程中的每一个节点(无论是自动任务还是人工任务)都可以从这个背包里读取数据,也可以往里面放入新的数据,或者更新已有的数据。这个“背包”里的数据,就是流程变量。
那么流程变量有什么作用呢?
流程变量是连接 流程模型 (BPMN) 和 业务逻辑 (Java代码) 的桥梁。它的核心作用体现在以下几个方面:
驱动流程决策 (Driving Decisions)
这是最常见的用途。排他网关、条件顺序流等决策节点会读取流程变量的值,来决定流程下一步该走向哪条分支。
示例:在请假流程中,经理审批后设置一个布尔型变量 approved。后续的网关会检查
a
p
p
r
o
v
e
d
=
=
t
r
u
e
来决定是走向“批准”路径还是“驳回”路径。存储业务关键数据
(
S
t
o
r
i
n
g
B
u
s
i
n
e
s
s
D
a
t
a
)
流程需要处理的数据,如订单金额、请假天数、申请人
I
D
等,都应该作为流程变量存储起来。示例:请假流程启动时,将
l
e
a
v
e
D
a
y
s
(
请假天数
)
和
r
e
a
s
o
n
(
请假事由
)
存入流程变量。后续的任何节点都可以随时获取这些信息。动态分配任务
(
D
y
n
a
m
i
c
T
a
s
k
A
s
s
i
g
n
m
e
n
t
)
用户任务的办理人、候选人或候选组通常不是写死的,而是根据流程中的数据动态决定的。示例:通过一个流程变量
d
e
p
a
r
t
m
e
n
t
M
a
n
a
g
e
r
I
d
来指定审批任务的办理人:
f
l
o
w
a
b
l
e
:
a
s
s
i
g
n
e
e
=
"
{approved == true} 来决定是走向“批准”路径还是“驳回”路径。 存储业务关键数据 (Storing Business Data) 流程需要处理的数据,如订单金额、请假天数、申请人ID等,都应该作为流程变量存储起来。 示例:请假流程启动时,将 leaveDays (请假天数) 和 reason (请假事由) 存入流程变量。后续的任何节点都可以随时获取这些信息。 动态分配任务 (Dynamic Task Assignment) 用户任务的办理人、候选人或候选组通常不是写死的,而是根据流程中的数据动态决定的。 示例:通过一个流程变量 departmentManagerId 来指定审批任务的办理人:flowable:assignee="
approved==true来决定是走向“批准”路径还是“驳回”路径。存储业务关键数据(StoringBusinessData)流程需要处理的数据,如订单金额、请假天数、申请人ID等,都应该作为流程变量存储起来。示例:请假流程启动时,将leaveDays(请假天数)和reason(请假事由)存入流程变量。后续的任何节点都可以随时获取这些信息。动态分配任务(DynamicTaskAssignment)用户任务的办理人、候选人或候选组通常不是写死的,而是根据流程中的数据动态决定的。示例:通过一个流程变量departmentManagerId来指定审批任务的办理人:flowable:assignee="{departmentManagerId}"。
为服务任务提供输入/输出 (In/Out for Service Tasks)
当流程执行到一个服务任务(Service Task)时,它可以从流程变量中获取执行所需的输入参数,并在执行完毕后,将结果作为新的流程变量存回“背包”中。
示例:一个“计算利息”的服务任务,需要从变量中读取 principal (本金) 和 rate (利率),计算后将结果 interest 存回变量。
流程变量的数据类型
流程变量可以存储所有可被Java序列化的对象。常见的数据类型包括:
String
Integer, Long, Double
Boolean
Date
List, Map
自定义的Java对象 (POJO),只要该对象实现了 java.io.Serializable 接口。!!!!!!!!!!!!!
注意:Flowable会将这些变量序列化后存储在数据库的 ACT_RU_VARIABLE (运行时) 和 ACT_HI_VARINST (历史) 表中。
如何操作流程变量 (Java API)
主要通过 RuntimeService 和 TaskService 来管理流程变量。
1. 在启动流程时设置变量
这是设置初始变量最常用的方式。
Map<String, Object> variables = new HashMap<>();
variables.put("initiator", "john_doe");
variables.put("leaveDays", 3);
variables.put("reason", "家庭事务");
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("leaveRequestProcess", variables);
2. 在完成任务时设置变量
当用户完成一个任务时,通常会产生新的数据,这些数据需要作为流程变量更新。
Map<String, Object> variables = new HashMap<>();
variables.put("approved", true);
variables.put("managerComment", "情况属实,同意。");
taskService.complete(taskId, variables);
这里的变量会合并到流程实例的全局变量中。如果已有同名变量,其值会被覆盖。
3. 在流程运行的任何时候设置或获取变量
你可以随时主动地为某个正在运行的流程实例设置或获取变量。
// 设置单个变量
runtimeService.setVariable(processInstanceId, "someKey", "someValue");
// 设置多个变量
Map<String, Object> newVariables = ...;
runtimeService.setVariables(processInstanceId, newVariables);
// 获取单个变量
Integer days = (Integer) runtimeService.getVariable(processInstanceId, "leaveDays");
// 获取所有变量
Map<String, Object> allVariables = runtimeService.getVariables(processInstanceId);
全局变量局部变量
理解全局变量 (Global Variables) 和 局部变量 (Local Variables) 的区别,能让你的流程设计更加精炼、高效和无污染。
我们将通过一个生动的比喻来开始,然后再深入技术细节。
核心比喻:长途旅行的“背包” vs. 某一站的“临时便签”
全局变量 (Global Variables) - “旅行背包”
想象一个流程实例是一次长途旅行。全局变量就是你随身携带的主背包。
这个背包从旅行开始(流程启动)就一直跟着你,直到旅行结束(流程终结)。
在旅途的任何一站(任何任务节点),你都可以打开背包,查看里面的东西(如护照、钱),或者往里面放新东西(如买的纪念品)。
特点:全局共享、持久存在于整个流程实例中。
局部变量 (Local Variables) - “临时便签”
局部变量就像你在旅途中某一站(某个特定任务)时,贴在当地地图上的一张临时便签。
这张便签上可能写着:“提醒我在这里买水”,或者记录一些临时的想法。
这张便签只在你停留于这一站时才有意义。一旦你处理完这一站的事情,离开这里(任务完成),这张便签就会被丢弃。它不会跟着你进入下一站。
特点:范围受限、生命周期短暂。
一、 全局变量 (Global Variables) 详解
全局变量是与整个流程实例 (Process Instance) 绑定的变量。
范围 (Scope):整个流程实例。
生命周期 (Lifecycle):从流程实例创建开始,直到该实例彻底结束(进入历史库)。
可见性 (Visibility):在流程实例的任何一个活动节点(无论是用户任务、服务任务还是网关)都可以被访问和修改。
主要用途:
存储驱动流程走向的关键数据,如 approved, leaveDays。
存储贯穿整个流程的业务标识符,如 orderId, applicantId。
在不同任务节点之间传递数据。
API 操作:
设置:runtimeService.setVariable(processInstanceId, “key”, value) 或 taskService.setVariable(taskId, “key”, value) (注意:TaskService的这个方法是设置全局变量的便捷方式)。
获取:runtimeService.getVariable(processInstanceId, “key”) 或 taskService.getVariable(taskId, “key”)。
二、 局部变量 (Local Variables) 详解
局部变量是仅仅与流程中的某个特定执行 (Execution) 或任务 (Task) 绑定的变量。
范围 (Scope):仅限于定义它的那个任务或执行。
生命周期 (Lifecycle):非常短暂。当该任务完成或该执行继续向前推进后,局部变量就会被销毁,不复存在。
可见性 (Visibility):只有在它所属的任务或执行的上下文中才能被访问。流程的其他部分对它一无所知。
主要用途:
存储仅用于当前任务的临时数据,避免污染全局范围。
用于控制当前任务UI的特定状态(例如,表单某个部分的展开/折叠状态)。
在任务的监听器 (Task Listener) 中传递临时数据。
API 操作:注意方法名中的 Local 后缀!
设置:taskService.setVariableLocal(taskId, “key”, value)。
获取:taskService.getVariableLocal(taskId, “key”)。