1. 概念
流程变量在 activiti 中是一个非常重要的角色,流程运转有时需要靠流程变量,业务系统和 activiti 结合时少不了流程变量,流程变量就是 activiti 在管理工作流时根据管理需要而设置的变量。 如:在出差申请流程流转时如果出差天数大于 3 天则由总经理审核,否则由人事直接审核, 出差天数就可以设置为流程变量,在流程流转时使用。
注:虽然流程变量中可以存储业务数据,可以通过activiti的api查询流程变量从而实现查询业务数据, 但是不建议这样使用,因为业务数据查询由业务系统负责,activiti设置流程变量是为了流程执行需要而创建的。
2. 流程变量类型
如果将 pojo 存储到流程变量中,必须实现序列化接口 serializable,为了防止由于新增字段无法反序列化,需要生成 serialVersionUID
3. 流程变量作用域
流程变量的作用域可以是一个流程实例(processInstance),或一个任务(task),或一个执行实例 (execution)
global变量
流程变量的默认作用域是流程实例,当一个流程变量的作用域为流程实例时,可以称为 global 变量
注:Global变量:userId(变量名)、xxx(变量值) global 变量中变量名不允许重复,设置相同名称的变量,后设置的值会覆盖前设置的变量值
local变量
任务和执行实例仅仅是针对一个任务和一个执行实例范围,范围没有流程实例大, 称为 local 变量。Local 变量由于在不同的任务或不同的执行实例中,作用域互不影响,变量名可以相同没有影响。Local 变量名也可以和 global 变量名相同,也是没有影响的
4. 流程表变量的使用方法
(1)在属性上使用UEL表达式
可以在 assignee 处设置 UEL 表达式,表达式的值为任务的负责人,比如: ${assignee}, assignee 就 是一个流程变量名称, Activiti获取UEL表达式的值,即流程变量assignee的值 ,将assignee的值作为任务的负责人进行任务分配
(2)在连线上使用UEL表达式
可以在连线上设置UEL表达式,决定流程走向。 比如:${price<10000} ,price就是一个流程变量名称,uel表达式结果类型为布尔类型, 如果UEL表达式是true,则决定流程执行走向(即流程走这条连线)
5. 使用流程变量
例:员工创建出差申请单,由部门经理审核,部门经理申请通过后3天以下由财务直接申批,3天以上先由总经理审批,总经理审批通过后再由财务审批
(1)流程定义
先通过UEL-value来设置负责人
然后在分支线上来设置条件
注:此处还可以通过对象参数命名,比如 evection.num
另一根线对应的设置
设置完成之后即可部署流程
(2)使用global变量
创建pojo对象
public class Evection implements Serializable {
/**
* id
*/
private long id;
/**
* 名称
*/
private String evectionName;
/**
* 出差天数
*/
private double num;
/**
* 开始日期
*/
private Date startDate;
/**
* 结束日期
*/
private Date endDate;
/**
* 目的地
*/
private String destination;
/**
* 事由
*/
private String reason;
public Evection() {
}
public Evection(long id, String evectionName, double num, Date startDate, Date endDate, String destination, String reason) {
this.id = id;
this.evectionName = evectionName;
this.num = num;
this.startDate = startDate;
this.endDate = endDate;
this.destination = destination;
this.reason = reason;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getEvectionName() {
return evectionName;
}
public void setEvectionName(String evectionName) {
this.evectionName = evectionName;
}
public double getNum() {
return num;
}
public void setNum(double num) {
this.num = num;
}
public Date getStartDate() {
return startDate;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
public Date getEndDate() {
return endDate;
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
public String getDestination() {
return destination;
}
public void setDestination(String destination) {
this.destination = destination;
}
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
@Override
public String toString() {
return "Evection{" +
"id=" + id +
", evectionName='" + evectionName + '\'' +
", num=" + num +
", startDate=" + startDate +
", endDate=" + endDate +
", destination='" + destination + '\'' +
", reason='" + reason + '\'' +
'}';
}
}
部署流程
@Test
public void deploy() {
//1.获取ProcessEngine对象
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
//2.获取RepositoryService
RepositoryService service = engine.getRepositoryService();
//3.部署
Deployment deploy = service.createDeployment()
.addClasspathResource("bpmn/evection-variable.bpmn")
.addClasspathResource("bpmn/evection-variable.png")
.name("出差申请流程-Variable")
.deploy();
System.out.println("id: " + deploy.getId());
System.out.println("name: " + deploy.getName());
}
设置流程变量
a. 启动流程时设置,变量的作用域是整个流程实例
通过startProcessInstanceByKey方法设置流程变量的作用域是一个流程实例,流程变量使用Map存储,同一个流程实例map中的key相同时,后者会覆盖前者
@Test
public void startAndSet() {
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = engine.getRuntimeService();
String key = "evection-variable";
Map<String, Object> variables = new HashMap<>();
Evection evection = new Evection();
evection.setNum(2d);
variables.put("evection", evection);
variables.put("assignee0", "zhangsan");
variables.put("assignee1", "lisi");
variables.put("assignee2", "wangwu");
variables.put("assignee3", "xiaoming");
ProcessInstance instance = runtimeService.startProcessInstanceByKey(key, variables);
System.out.println("流程实例名称:" + instance.getName());
System.out.println("流程定义id:" + instance.getProcessDefinitionId());
}
处理任务
@Test
public void completeTask() {
String key = "evection-variable";
String assignee = "lisi";
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = engine.getTaskService();
Task task = taskService.createTaskQuery().processDefinitionKey(key).taskAssignee(assignee).singleResult();
if (task != null) {
taskService.complete(task.getId());
System.out.println("任务:" + task.getId() + "," + task.getName() + ",完成");
}
}
b. 处理任务时设置
在完成任务时设置流程变量,该流程变量只有在该任务完成后其它结点才可使用该变量,它的作用域是整个流程实例,如果设置的流程变量的key在流程实例中已存在相同的名字则后设置的变量会替换前边设置的变量
@Test
public void startProcess() {
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = engine.getRuntimeService();
String key = "evection-variable";
Map<String, Object> variables = new HashMap<>();
variables.put("assignee0", "zhangsan");
variables.put("assignee1", "lisi");
variables.put("assignee2", "wangwu");
variables.put("assignee3", "xiaoming");
ProcessInstance instance = runtimeService.startProcessInstanceByKey(key, variables);
System.out.println("流程实例名称:" + instance.getName());
System.out.println("流程定义id:" + instance.getProcessDefinitionId());
}
处理时设置
@Test
public void doingSet() {
String taskId = "1404";
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = processEngine.getTaskService();
Map<String, Object> variables = new HashMap<>();
Evection evection = new Evection();
evection.setNum(3d);
variables.put("evection", evection);
taskService.setVariablesLocal(taskId, variables);
taskService.complete(taskId);
}
注: 通过当前任务设置流程变量,需要指定当前任务id,如果当前执行的任务id不存在则抛出异常(任务办理时也是通过map设置流程变量,一次可以设置多个变量)
c. 当前流程实例设置
通过流程实例id设置全局变量,该流程实例必须未执行完成(即该流程实例还没有走完/结束)
@Test
public void setLocalVariableByTaskId(){
String taskId="1404";
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = processEngine.getTaskService();
Evection evection = new Evection ();
evection.setNum(3d);
taskService.setVariableLocal(taskId, "evection", evection);
// 可以通过map一次设置多个值
//taskService.setVariablesLocal(taskId, variables)
}
注:任务id必须是当前待办的任务id,act_ru_task中存在,如果该任务已结束,会抛出异常,同时也可以通过 taskService.getVariable() 方法获取流程变量
(3)设置local变量
a. 任务办理时设置
任务办理时设置local流程变量,当前运行的流程实例只能在该任务结束前使用,任务结束该变量无法在 当前流程实例使用,可以通过查询历史任务查询
@Test
public void completTask() {
//任务id
String taskId = "1404";
//获取processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = processEngine.getTaskService();
//定义流程变量
Map<String, Object> variables = new HashMap<String, Object>();
Evection evection = new Evection ();
evection.setNum(3d);
//定义流程变量
Map<String, Object> variables = new HashMap<>();
//变量名是evection,变量值是evection对象
variables.put("evection", evection);
//设置local变量,作用域为该任务
taskService.setVariablesLocal(taskId, variables);
//完成任务
taskService.complete(taskId);
}
注:作用域为当前任务,每个任务可以设置同名的变量,互不影响
b. 通过当前任务设置
@Test
public void setLocalVariableByTaskId(){
String taskId="1404";
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = processEngine.getTaskService();
Evection evection = new Evection ();
evection.setNum(3d);
taskService.setVariableLocal(taskId, "evection", evection);
// 可以通过map一次设置多个值
//taskService.setVariablesLocal(taskId, variables)
}
注:同理全局变量设置时的前提条件,即当前任务不能执行完/结束
c. 补充
部门经理审核、总经理审核、财务审核时设置local变量,可通过historyService查询每个历史任务时一起将流程变量的值也查询出来
@Test
public void queryHistoryInfo() {
//创建历史任务查询对象
HistoricTaskInstanceQuery historicTaskInstanceQuery = historyService.createHistoricTaskInstanceQuery();
//查询结果包括local变量
historicTaskInstanceQuery.includeTaskLocalVariables();
for (HistoricTaskInstance historicTaskInstance : list) {
System.out.println("==============================");
System.out.println("任务id:" + historicTaskInstance.getId());
System.out.println("任务名称:" + historicTaskInstance.getName());
System.out.println("任务负责人:" + historicTaskInstance.getAssignee());
System.out.println("任务local变量:"+ historicTaskInstance.getTaskLocalVariables());
}
评论 (0)