流程變量
流程變量在 activiti
中是一個非常重要的角色,流程運轉有時需要靠流程變量,業務系統和 activiti
結合時少不了流程變量,流程變量就是 activiti
在管理工作流時根據管理需要而設置的變量。
比如在請假流程流轉時如果請假天數大於 3 天則由總經理審覈,否則由人事直接審覈,請假天數就可以設置爲流程變量,在流程流轉時使用。
注意:雖然流程變量中可以存儲業務數據可以通過 activiti
的 api
查詢流程變量從而實現查詢業務數據,但是不建議這樣使用,因爲業務數據查詢由業務系統負責,activiti
設置流程變量是爲了流程執行需要而創建。
流程變量類型
注意:如果將pojo
存儲到流程變量中,必須實現序列化接口 serializable
,爲了防止由於新增字段無
法反序列化,需要生成 serialVersionUID
。
流程變量作用域
流程變量的作用域默認是一個流程實例(processInstance
),也可以是一個任務(task
)或一個執行實例(execution
)
- 流程實例的範圍最大,可以稱爲
global 變量
- global 變量中變量名不允許重複
- 設置相同名稱的變量,後設置的值會覆蓋前設置的變量值。
- 任務和執行實例僅僅是針對一個任務和一個執行實例範圍,範圍沒有流程實例大,稱爲
local 變量
Local 變量
由於在不同的任務或不同的執行實例中,作用域互不影響,變量名可以相同沒有影響。Local 變量名
也可以和global 變量名
相同,沒有影響。
流程變量的使用方法
- 第一步:設置流程變量
- 第二步:通過 UEL 表達式使用流程變量
-
可以在
assignee
處設置UEL 表達式
,表達式的值爲任務的負責人
比如:${assignee}
,assignee
就是一個流程變量名稱
-
可以在連線上設置
UEL 表達式
,決定流程走向
比如:${price>=10000}
和${price<10000}
:price
就是一個流程變量名稱,uel
表達式結果類型爲布爾類型
如果UEL 表達式
是true
,要決定 流程執行走向
-
使用 Global
變量控制流程
需求:
員工創建請假申請單,由部門經理審覈,部門經理審覈通過後請假 3 天及以下由人事經理直接審覈,3 天以上先由總經理審覈,總經理審覈通過再由人事經理存檔。
流程定義
請假天數大於等於 3 連線條件:
請假天數小於 3 連線條件:
Condition
也可以設置爲${holiday.num}
設置 global
流程變量
在部門經理審覈前設置流程變量,變量值爲請假單信息(包括請假天數),部門經理審覈後可以根據流程變量的值決定流程走向。
啓動流程時設置
在啓動流程時設置流程變量,變量的作用域是整個流程實例。
通過 map<key,value>
設置流程變量,map
中可以設置多個變量,這個key
就是流程變量的名字。
// 啓動流程時設置流程變量
@Test
public void startProcessInstance() {
// 流程定義key
String processDefinitionKey = "";
Holiday holiday = new Holiday();
holiday.setNum(3);
// 定義流程變量
Map<String, Object> variables = new HashMap<String, Object>();
//變量名是num,變量值是holiday.getNum(),變量名也可以是一個對象
variables.put("num", holiday.getNum());
RuntimeService runtimeService = processEngine.getRuntimeService();
ProcessInstance processInstance = runtimeService
.startProcessInstanceByKey(processDefinitionKey, variables);
System.out.println(" 流 程 實 例 id:" +
processInstance.getProcessInstanceId());
}
說明:
startProcessInstanceByKey(processDefinitionKey, variables)
流程變量作用域是一個流程實例,流程變量使用 Map
存儲,同一個流程實例設置變量 map
中key
相同,後者覆蓋前者。
任務辦理時設置
在完成任務時設置流程變量,該流程變量只有在該任務完成後其它結點纔可使用該變量,它的作用域是整個流程實例,如果設置的流程變量的key
.在流程實例中已存在相同的名字則後設置的變量替換前邊設置的變量。
這裏需要在創建請假單任務完成時設置流程變量
// 辦理任務時設置流程變量
@Test
public void completTask() {
//任務id
String taskId = "";
TaskService taskService = processEngine.getTaskService();
Holiday holiday = new Holiday();
holiday.setNum(4);
// 定義流程變量
Map<String, Object> variables = new HashMap<String, Object>();
//變量名是holiday,變量值是holiday對象
variables.put("holiday", holiday);
taskService.complete(taskId, variables);
}
說明:
通過當前任務設置流程變量,需要指定當前任務id
,如果當前執行的任務 id
不存在則拋出異常。
任務辦理時也是通過map<key,value>
設置流程變量,一次可以設置多個變量。
通過當前流程實例設置
通過流程實例 id
設置全局變量,該流程實例必須未執行完成。
public void setGlobalVariableByExecutionId(){
//當前流程實例執行 id,通常設置爲當前執行的流程實例
String executionId="2601";
RuntimeService runtimeService = processEngine.getRuntimeService();
Holiday holiday = new Holiday();
holiday.setNum(3);
//通過流程實例 id設置流程變量
runtimeService.setVariable(executionId, "holiday", holiday);
//一次設置多個值
//runtimeService.setVariables(executionId, variables)
}
注意:
executionId
必須當前未結束 流程實例的執行 id
,通常此id
設置流程實例 的 id
。
也可以通過 runtimeService.getVariable()
獲取流程變量
通過當前任務設置
public void setGlobalVariableByTaskId(){
//當前待辦任務id
String taskId="1404";
TaskService taskService = processEngine.getTaskService();
Holiday holiday = new Holiday();
holiday.setNum(3);
//通過任務設置流程變量
taskService.setVariable(taskId, "holiday", holiday);
//一次設置多個值
//taskService.setVariables(taskId, variables)
}
注意:
任務id
必須是當前待辦任務id
,act_ru_task
中存在。如果該任務已結束,報錯:
也可以通過 taskService.getVariable()
獲取流程變量。
測試
正常測試:
- 設置流程變量的值大於等於 3 天
- 設計流程變量的值小於 3 天
異常測試:
- 流程變量不存在
- 流程變量的值爲空
NULL
,price
屬性爲空 UEL
表達式都不符合條件- 不設置連線的條件
注意事項
- 如果
UEL
表達式中流程變量名不存在則報錯。 - 如果
UEL
表達式中流程變量值爲空NULL
,流程不按UEL
表達式去執行,而流程結束 。 - 如果
UEL
表達式都不符合條件,流程結束 - 如果連線不設置條件,會走
flow
序號小的那條線
操作數據庫表
設置流程變量會在當前執行流程變量表插入記錄,同時也會在歷史流程變量表也插入記錄。
當前流程變量表
SELECT * FROM act_ru_variable
記錄當前運行流程實例可使用的流程變量,包括 global
和local
變量
字段 | 說明 |
---|---|
Id_ |
主鍵 |
Type_ |
變量類型 |
Name_ |
變量名稱 |
Execution_id_ |
所屬流程實例執行 id,global 和 local 變量都存儲 |
Proc_inst_id_ |
所屬流程實例 id,global 和 local 變量都存儲 |
Task_id_ |
所屬任務 id,local 變量存儲 |
Bytearray_ |
serializable 類型變量存儲對應 act_ge_bytearray 表的 id |
Double_ |
double 類型變量值 |
Long_ |
long 類型變量值 |
Text_ |
text 類型變量值 |
歷史流程變量表
SELECT * FROM act_hi_varinst
記錄所有已創建的流程變量,包括global
和local
變量
字段意義參考當前流程變量表。
代碼
啓動時設置流程變量
/**
* com.lxf.activiti.processInstance
* 請假實體類:
* 注意POJO類型,一定要實現Serializable接口,否則在存儲這個pojo時就會報異常
* @author lxf
* @version 1.0
* @date 2020/4/27 7:09
*/
public class Holiday implements Serializable {
private Integer id;
private String holidayName;//申請人的名字
private Date beginDate;//開始時間
private Date endDate;//結束日期
private Float num;//請假天數
private String reason;//事由
private String type;//請假類型
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getHolidayName() {
return holidayName;
}
public void setHolidayName(String holidayName) {
this.holidayName = holidayName;
}
public Date getBeginDate() {
return beginDate;
}
public void setBeginDate(Date beginDate) {
this.beginDate = beginDate;
}
public Date getEndDate() {
return endDate;
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
public Float getNum() {
return num;
}
public void setNum(Float num) {
this.num = num;
}
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
測試
/**
* com.lxf.activiti.processInstance
* 流程變量的測試
* @author lxf
* @version 1.0
* @date 2020/4/27 7:10
*/
public class VariableTest {
public static void main(String[] args) {
VariableTest variableTest = new VariableTest();
variableTest.processDeploy();
}
/**
* 1. 新的請假流程定義的部署
*/
public void processDeploy(){
//1.得到ProcessEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到RepositoryService對象
RepositoryService repositoryService = processEngine.getRepositoryService();
//3.部署
Deployment deploy = repositoryService.createDeployment()
.addClasspathResource("diagram/holiday4.bpmn")
.addClasspathResource("diagram/holiday4.png")
.name("請假流程-流程變量")
.deploy();
System.out.println(deploy.getId());
System.out.println(deploy.getName());
}
/**
* 2. 啓動流程實例,同時還要設置流程變量的值
* act_ge_bytearray
* act_ru_variable
*/
public void startProcessInstance(){
//1.得到ProcessEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到RuntimeService
RuntimeService runtimeService = processEngine.getRuntimeService();
//3.流程定義的key問題 myProcess_1
String key = "myProcess_1";
Map<String ,Object> map = new HashMap<>();
Holiday holiday = new Holiday();
holiday.setNum(5F);
map.put("holiday",holiday);
//4.啓動流程實例,並且設置流程變量的值
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(key, map);
//5.輸出實例信息
System.out.println(processInstance.getName());
System.out.println(processInstance.getProcessDefinitionId());
//6.通過實例id,來設置流程變量
//第一個參數:流程實例的id
//第二個參數:流程變量名
//第三個變量:流程變量名,所對應的值
// runtimeService.setVariable(processInstance.getId(),"holiday",map);
}
/**
* 完成任務 zhangsan -----lishi----判斷流程變量的請假天數,1天----分支:人事經理存檔(zhaoliu)
*/
public void complete(){
//1.得到ProcessEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到TaskService
TaskService taskService = processEngine.getTaskService();
//3.查詢當前用戶是否有任務
String key = "myProcess_1";
Task task = taskService.createTaskQuery().processDefinitionKey(key)
.taskAssignee("zhaoliu").singleResult();
//4.判斷task!=null,說明當前用戶有任務
if(task!=null){
taskService.complete(task.getId());
// 可以設置流程變量的值
// taskService.complete(task.getId(),map);
System.out.println("任務執行完畢");
}
}
}
設置 local
流程變量
任務辦理時設置
任務辦理時設置local
流程變量,當前運行的流程實例只能在該任務結束前使用,任務結束該變量無法在當前流程實例使用,可以通過查詢歷史任務查詢。
// 辦理任務時設置local流程變量
@Test
public void completTask() {
//任務id
String taskId = "";
TaskService taskService = processEngine.getTaskService();
// 定義流程變量
Map<String, Object> variables = new HashMap<String, Object>();
Holiday holiday = new Holiday ();
holiday.setNum(3);
// 定義流程變量
Map<String, Object> variables = new HashMap<String, Object>();
//變量名是holiday,變量值是holiday對象
variables.put("holiday", holiday);
// 設置local變量,作用域爲該任務
taskService.setVariablesLocal(tasked, variables);
taskService.complete(taskId);
}
說明:
設置作用域爲任務的 local
變量,每個任務可以設置同名的變量,互不影響。
與全局變量的區別爲setVariablesLocal
,全局變量爲setVariables
通過當前任務設置
@Test
public void setLocalVariableByTaskId(){
//當前待辦任務id
String taskId="1404";
TaskService taskService = processEngine.getTaskService();
Holiday holiday = new Holiday ();
holiday.setNum(3);
//通過任務設置流程變量
taskService.setVariableLocal(taskId, "holiday", holiday);
//一次設置多個值
//taskService.setVariablesLocal(taskId, variables)
}
注意:
任務 id
必須是當前待辦任務id
,act_ru_task
中存在。
Local
變量測試
Local
變量在任務結束後無法在當前流程實例執行中使用,如果後續的流程執行需要用到此變量則會報錯
在部門經理審覈、總經理審覈、人事經理審覈時設置 local
變量,可通過 historyService
查詢每個歷史任務時將流程變量的值也查詢出來。
// 創建歷史任務查詢對象
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());
}
注意:查詢歷史流程變量,特別是查詢 pojo 變量需要經過反序列化,不推薦使用。