[TOC]
# 1. 需求
:-: 
文件:`evection-variable.bpmn`
員工創建出差申請單,由部門經理審核,部門經理審核通過后出差少于3天則由財務直接審批,3天及以上先由總經理審核,總經理審核通過再由財務審批。
# 2. 設置global變量
**1. 定義一個實體類**
```java
/**
* Java實體類存儲到流程變量中,必須實現序列化接口 Serializable
*/
@Data
public class Evection implements Serializable {
/**
* 為了防止由于新增字段無法反序列化,每個實體類需要生成 serialVersionUID
*/
private static final long serialVersionUID = 327322158719400704L;
/** 主鍵Id **/
private Long id;
/** 出差單的名字 **/
private String evectionName;
/** 出差天數 **/
private Double num;
/** 開始時間 **/
private Date beginDate;
/** 出差結束時間 **/
private Date endDate;
/** 目的地 **/
private String destination;
/** 出差原因 **/
private String reson;
}
```
**2. 可以在以下地方設置global變量**
>[info]1. 啟動流程時設置global變量
(1)啟動流程程序。
```java
/**
* ===========設置global變量位置1:啟動流程時設置global變量===========
* 在啟動流程時設置流程變量,變量的作用域是整個流程實例
*/
@Test
public void startProcessSetVariable() {
//獲取流程引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//獲取RunTimeService
RuntimeService runtimeService = processEngine.getRuntimeService();
//流程定義Key
String key = "evection-variable";
Map<String, Object> variables = new HashMap<>();
Evection evection = new Evection();
//設置出差日期為2天
evection.setNum(2d);
variables.put("evection", evection);
variables.put("assignee0", "李四");
variables.put("assignee1", "王經理");
variables.put("assignee2", "楊總經理");
variables.put("assignee3", "張財務");
//啟動流程并設置變量
runtimeService.startProcessInstanceByKey(key, variables);
}
```
(2)查看數據庫已經存在流程變量了。
```sql
# 該表存儲當前流程實例的變量,當流程實例被完成時,這些變量也就被刪除了
mysql> select * from act_ru_variable;
+-------+------+--------------+-----------+---------------+---------------+----------+---------------+---------+-------+----------+--------+
| ID_ | REV_ | TYPE_ | NAME_ | EXECUTION_ID_ | PROC_INST_ID_ | TASK_ID_ | BYTEARRAY_ID_ | DOUBLE_ | LONG_ | TEXT_ | TEXT2_ |
+-------+------+--------------+-----------+---------------+---------------+----------+---------------+---------+-------+----------+--------+
| 20002 | 1 | string | assignee3 | 20001 | 20001 | NULL | NULL | NULL | NULL | 張財務 | NULL |
| 20004 | 1 | serializable | evection | 20001 | 20001 | NULL | 20003 | NULL | NULL | NULL | NULL |
| 20006 | 1 | string | assignee0 | 20001 | 20001 | NULL | NULL | NULL | NULL | 李四 | NULL |
| 20007 | 1 | string | assignee2 | 20001 | 20001 | NULL | NULL | NULL | NULL | 楊總經理 | NULL |
| 20008 | 1 | string | assignee1 | 20001 | 20001 | NULL | NULL | NULL | NULL | 王經理 | NULL |
+-------+------+--------------+-----------+---------------+---------------+----------+---------------+---------+-------+----------+--------+
```
(3)完成個人任務。
:-: 
```java
/**
* 完成個人任務
*/
@Test
public void completTask() {
//流程定義Key
String key = "evection-variable";
//任務負責人
String assingee = "李四";
//String assingee = "王經理";
//String assingee = "楊總經理";
//String assingee = "張財務";
//獲取流程引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//獲取taskservice
TaskService taskService = processEngine.getTaskService();
//查詢任務
Task task = taskService.createTaskQuery()
.processDefinitionKey(key)
.taskAssignee(assingee)
.singleResult();
if (task != null) {
//根據任務id來完成任務
taskService.complete(task.getId());
System.out.println(assingee + "完成了他的任務!");
} else {
System.out.println(assingee + "沒有要完成的任務!");
}
}
```
依次的更換負責人,控制臺輸出如下:
```
李四完成了他的任務!
王經理完成了他的任務!
楊總經理沒有要完成的任務!
張財務完成了他的任務!
```
可以看到總經理沒有任務,因為出差的天數我們設置為2天,所以直接到財務審批了。
>[info]2. 其他設置global變量的位置,這里就不測試了
```java
public class TestVariables {
/**
* ===========設置global變量位置2:當前任務完成時設置global變量===========
* 1) 在完成任務時設置流程變量,該流程變量只有在該任務完成后其它結點才可使用該變量,
* 它的作用域是整個流程實例,如果設置的流程變量的key在流程實例中已存在相同的名字
* 則后設置的變量替換前邊設置的變量。
* 2) 通過當前任務設置流程變量,需要指定當前任務id,如果當前執行的任務id不存在則拋出異常。
*/
@Test
public void completTaskSetVariable() {
//流程定義key
String key = "evection-variable";
//任務負責人
String assingee = "張三";
//獲取processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//創建TaskService
TaskService taskService = processEngine.getTaskService();
//創建變量集合
Map<String, Object> map = new HashMap<>();
Evection evection = new Evection();
//設置出差天數
evection.setNum(2d);
//定義流程變量
map.put("evection", evection);
//獲取任務
Task task = taskService.createTaskQuery()
.processDefinitionKey(key)
.taskAssignee(assingee)
.singleResult();
if (task != null) {
//完成任務后設置流程變量
taskService.complete(task.getId(), map);
System.out.println("任務執行完成!");
} else {
System.out.println("沒有任務要完成!");
}
}
/**
* ===========設置global變量位置3:在當前流程實例設置global變量===========
* 通過流程實例id設置全局變量,該流程實例必須未執行完成。
*/
@Test
public void setGlobalVariableByExecutionId() {
//當前流程實例執行id,通常設置為當前執行的流程實例
String executionId = "2601";
// 獲取processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//獲取RuntimeService
RuntimeService runtimeService = processEngine.getRuntimeService();
//創建出差pojo對象
Evection evection = new Evection();
//設置天數
evection.setNum(3d);
//通過流程實例 id設置流程變量
runtimeService.setVariable(executionId, "evection", evection);
//一次設置多個值
//runtimeService.setVariables(executionId, variables)
}
/**
* ===========設置global變量位置4:通過當前任務設置global變量===========
* 任務id必須是當前待辦任務id,即該id在表act_ru_task中存在。如果該任務已結束,會報錯。
*/
@Test
public void setGlobalVariableByTaskId() {
//當前待辦任務id
String taskId = "1404";
//獲取processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = processEngine.getTaskService();
Evection evection = new Evection();
evection.setNum(3d);
//通過任務設置流程變量
taskService.setVariable(taskId, "evection", evection);
//一次設置多個值
//taskService.setVariables(taskId, variables)
}
}
```
```sql
# 歷史變量可以到表act_hi_varinst中查看
mysql> select * from act_hi_varinst;
+-------+---------------+---------------+----------+-----------+--------------+------+---------------+---------+-------+--
| ID_ | PROC_INST_ID_ | EXECUTION_ID_ | TASK_ID_ | NAME_ | VAR_TYPE_ | REV_ | BYTEARRAY_ID_ | DOUBLE_ | LONG_
+-------+---------------+---------------+----------+-----------+--------------+------+---------------+---------+-------+--
| 45002 | 45001 | 45001 | NULL | assignee3 | string | 0 | NULL | NULL | NULL | 張財務 | NULL | 20
| 45004 | 45001 | 45001 | NULL | evection | serializable | 0 | 45005 | NULL | NULL | NULL | NULL | 2
| 45006 | 45001 | 45001 | NULL | assignee0 | string | 0 | NULL | NULL | NULL | 李四 | NULL | 20
| 45007 | 45001 | 45001 | NULL | assignee2 | string | 0 | NULL | NULL | NULL | 楊總經理 | NULL | 2
```
# 3. 設置local變量
```java
public class TestVariables {
/**
* ===========設置local變量位置1:處理任務時設置local流程變量===========
* 任務辦理時設置local流程變量,當前運行的流程實例只能在該任務結束前使用,
* 任務結束該變量無法在當前流程實例使用,可以通過查詢歷史任務查詢。
*/
@Test
public void completTaskSetLocalVariable() {
//任務id
String taskId = "1404";
//獲取processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//獲取TaskService
TaskService taskService = processEngine.getTaskService();
//定義流程變量
Map<String, Object> variables = new HashMap<String, Object>();
Evection evection = new Evection();
evection.setNum(3d);
variables.put("evection", evection);
//設置local變量,作用域為該任務
taskService.setVariablesLocal(taskId, variables);
//完成任務
taskService.complete(taskId);
}
/**
* ===========設置local變量位置2:通過當前任務設置local流程變量===========
* 任務id必須是當前待辦任務id,即該id要在表act_ru_task中存在。
*/
@Test
public void setLocalVariableByTaskId() {
//當前待辦任務id
String taskId = "1404";
//獲取processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//獲取TaskService
TaskService taskService = processEngine.getTaskService();
Evection evection = new Evection();
evection.setNum(3d);
//通過任務設置流程變量
taskService.setVariableLocal(taskId, "evection", evection);
//一次設置多個值
//taskService.setVariablesLocal(taskId, Map)
}
/**
* 查詢歷史任務信息,包括設置的local變量等
*/
@Test
public void findHistoryTask() {
//獲取引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//獲取HistoryService
HistoryService historyService = processEngine.getHistoryService();
//創建歷史任務查詢對象
HistoricTaskInstanceQuery historicTaskInstanceQuery = historyService.createHistoricTaskInstanceQuery();
//流程定義key
historicTaskInstanceQuery.processDefinitionId("evection-variable:1:17503");
//查詢所有內容
List<HistoricTaskInstance> list = historicTaskInstanceQuery.list();
// 查詢結果包括 local變量
historicTaskInstanceQuery.includeTaskLocalVariables();
for (HistoricTaskInstance historicTaskInstance : list) {
System.out.println("任務id:" + historicTaskInstance.getId());
System.out.println("任務名稱:" + historicTaskInstance.getName());
System.out.println("任務負責人:" + historicTaskInstance.getAssignee());
System.out.println("任務local變量:"+ historicTaskInstance.getTaskLocalVariables());
System.out.println();
}
}
}
```
# 4. 注意事項
1、 如果UEL表達式中流程變量名不存在則報錯。
2、 如果UEL表達式中流程變量值為空NULL,流程不按UEL表達式去執行,而流程結束 。
3、 如果UEL表達式都不符合條件,流程結束。
4、 如果連線不設置條件,會走flow序號小的那條線。
- Activiti流程引擎
- 工作流介紹
- Activiti是什么
- Activiti流程處理步驟
- Activiti環境搭建
- 搭建步驟
- 表結構介紹
- ActivitiAPI結構
- 認識流程符號
- 流程設計器的使用
- 流程處理步驟
- 亂碼問題
- 流程實例
- 流程實例是什么
- 業務標識
- 查詢流程實例
- 掛起/激活流程實例
- 個人任務
- 分配任務負責人
- 查詢待辦任務
- 辦理權限
- 流程變量
- 流程變量類型
- 流程變量作用域
- 使用流程變量控制流程
- 組任務
- 設置任務候選人
- 組任務辦理流程
- 網關
- 4種網關類型
- 排他網關
- 并行網關
- 包含網關
- 事件網關
- Spring整合Activiti
- SpringBoot整合Activiti
- Flowable流程引擎
- Flowable是什么
- Flowable與Activiti
- Flowable環境搭建
- FlowableAPI
- 流程引擎API與服務
- 流程處理步驟
- 流程部署
- 流程部署方式
- 流程定義版本
- 刪除已部署的流程
- 下載資源
- 流程實例
- 什么是流程實例
- 業務標識
- 查詢流程實例
- 掛起/激活流程實例
- 分配任務負責人
- 固定分配
- UEL表達式分配
- 監聽器分配
- 辦理權限
- 流程變量
- 流程變量類型
- 流程變量作用域
- 流程變量控制流程
- 組任務
- 設置任務候選人
- 組任務辦理流程
- 網關
- 排他網關
- 并行網關
- 包含網關
- 事件網關
- 歷史查詢
- 查詢歷史
- Spring整合Flowable
- 配置文件整合
- 配置類整合
- SpringBoot整合Flowable