Activiti7工作流學習筆記二 流程實例
參與者(可以是用戶也可以是程序)按照流程定義內容發起一個流程,這就是一個流程實例。是動態的。
流程定義和流程實例的圖解:
流程定義部署在 activiti 後,就可以在系統中通過 activiti 去管理該流程的執行,執行流程表示流程的一次執行。
比如部署系統請假流程後,如果某用戶要申請請假這時就需要執行這個流程,如果另外一個用戶也要申請請假則也需要執行該流程,每個執行互不影響,每個執行是單獨的流程實例。
業務系統與Activiti整合原理
- 業務系統存儲具體的請假信息
- activiti中存儲流程相關的信息,並記錄業務標識(
businesskey
)
啓動流程實例時,指定的businesskey
,就會在act_ru_execution
(流程實例的執行表,當前流程進行的狀態,一條記錄)中存儲businesskey
。
Businesskey
:業務標識,通常爲業務表的主鍵
,業務標識和流程實例一一對應。業務標識來源於業務系統。存儲業務標識就是根據業務標識來關聯查詢業務系統的數據。
比如:請假流程啓動一個流程實例,就可以將請假單的 id 作爲業務標識存儲到 activiti 中,將來查詢activiti 的流程實例信息就可以獲取請假單的 id 從而關聯查詢業務系統數據庫得到請假單信息。
啓動流程實例,添加businessKey
/**
* com.lxf.activiti.ProcessDefinition
* 啓動流程實例,添加進businessKey
*
* 本質:act_ru_execution表中的businessKey的字段要存入業務標識
* @author lxf
* @version 1.0
* @date 2020/4/25 20:18
*/
public class BusinessKeyAdd {
public static void main(String[] args) {
//1.得到ProcessEngine對象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到RuntimeService對象
RuntimeService runtimeService = processEngine.getRuntimeService();
//3.啓動流程實例,同時還要指定業務標識businessKey 它本身就是請假單的id
//第一個參數:是指流程定義key
//第二個參數:業務標識businessKey
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holiday", "1001");
//4.輸出processInstance相關的屬性,取出businessKey使用:processInstance.getBusinessKey()
System.out.println(processInstance.getBusinessKey());
}
}
掛起、激活流程實例
某些情況可能由於流程變更需要將當前運行的流程暫停而不是直接刪除,流程暫停後將不會繼續執
行。
操作流程定義爲掛起狀態,該流程定義下邊所有的流程實例全部暫停:
流程定義爲掛起狀態該流程定義將不允許啓動新的流程實例,同時該流程定義下所有的流程實例將全部掛起暫停執行。
/**
* 全部流程實例掛起
*/
public void suspendOrActivateAllProcessDefinition(){
//1.得到ProcessEngine對象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到RepositoryService
RepositoryService repositoryService = processEngine.getRepositoryService();
//3.查詢流程定義的對象
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey("holiday").singleResult();
//4.得到當前流程定義的實例是否都爲暫停狀態
boolean suspended = processDefinition.isSuspended();
String processDefinitionId = processDefinition.getId();
//5.判斷
if(suspended){
//說明是暫停,就可以激活操作
repositoryService.activateProcessDefinitionById(processDefinitionId,true
,null);
System.out.println("流程定義:"+processDefinitionId+"激活");
}else{
repositoryService.suspendProcessDefinitionById(processDefinitionId,true,null);
System.out.println("流程定義:"+processDefinitionId+"掛起");
}
}
操作流程實例對象,針對單個流程執行掛起操作,某個流程實例掛起則此流程不再繼續執行,完成該流程實例的當前任務將報異常。
/**
* 單個流程實例掛起
*/
public void suspendOrActiveSingleProcessInstance(){
//1.得到ProcessEngine對象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到RuntimeService
RuntimeService runtimeService = processEngine.getRuntimeService();
//3.查詢流程實例對象
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
.processInstanceId("2501").singleResult();
//4.得到當前流程定義的實例是否都爲暫停狀態
boolean suspended = processInstance.isSuspended();
String processInstanceId = processInstance.getId();
//5.判斷
if(suspended){
//說明是暫停,就可以激活操作
runtimeService.activateProcessInstanceById(processInstanceId);
System.out.println("流程:"+processInstanceId+"激活");
}else{
runtimeService.suspendProcessInstanceById(processInstanceId);
System.out.println("流程定義:"+processInstanceId+"掛起");
}
}
個人任務
分配任務負責人
固定分配
在進行業務流程建模時指定固定的任務負責人
在properties
視圖中,填寫 Assignee
項爲任務負責人。
由於固定分配方式,任務只管一步一步執行任務,執行到每一個任務將按照 bpmn 的配置去分配任務負責人。
表達式分配
UEL
表達式:Activiti
使用 UEL
表達式,UEL
是java EE6
規範的一部分,UEL
(Unified Expression Language
)即統一表達式語言,activiti
支持兩個 UEL
表達式:UEL-value
和 UEL-method
。
-
UEL-value 定義如下:
assignee
這個變量是activiti
的一個流程變量。
或:
user
也是activiti
的一個流程變量,user.assignee
表示通過調用user
的getter
方法獲取值。 -
UEL-method
方式如下:
userBean
是spring
容器中的一個bean
,表示調用該bean
的getUserId()
方法。 -
UEL-method
與UEL-value
結合
再比如:
${ldapService.findManagerForEmployee(emp)}
,ldapService
是spring
容器的一個bean
,findManagerForEmployee
是該 bean 的一個方法,emp
是activiti
流程變量,emp
作爲參數傳到ldapService.findManagerForEmployee
方法中。 -
其它
表達式支持解析基礎類型、bean、list、array
和map
,也可作爲條件判斷。
如下:${order.price > 100 && order.price < 250}
使用流程變量分配任務
- 定義任務分配流程變量
- 設置流程變量
在啓動流程實例時設置流程變量,如下:
//啓動流程實例時設計流程變量
//定義流程變量
Map<String, Object> variables = new HashMap<String, Object>();
//設置流程變量assignee
variables.put("assignee", "張三");
ProcessInstance processInstance = runtimeService
.startProcessInstanceByKey(processDefinitionKey, variables);
由於使用了表達式分配,必須保證在任務執行過程表達式執行成功,比如:
某個任務使用了表達式${order.price > 100 && order.price < 250}
,當執行該任務時必須保證order
在流程變量中存在,否則activiti
異常.
動態設置assignee
/**
* com.lxf.activiti.processInstance
* 啓動流程實例,動態設置assignee
* @author lxf
* @version 1.0
* @date 2020/4/26 7:54
*/
public class AssigneeUEL {
public static void main(String[] args) {
//1.得到ProcessEngine對象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到RuntimeService對象
RuntimeService runtimeService = processEngine.getRuntimeService();
//3.設置assignee的取值 用戶可以在界面上設置流程的執行人
//key的值與流程定義中的UEL表達式對應
Map<String,Object> map = new HashMap<>();
map.put("assignee0","zhangsan");
map.put("assignee1","lishi");
map.put("assignee2","wangwu");
//4.啓動流程實例,同時還要設置流程定義的assignee的值
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holiday2", map);
//5.輸出
System.out.println(processEngine.getName());
}
}
監聽器分配
任務監聽器是發生對應的任務相關事件時執行自定義 java 邏輯 或表達式。
任務相當事件包括:
Create
:任務創建後觸發Assignment
:任務分配後觸發Delete
:任務完成後觸發All
:所有事件發生都觸發
java
邏輯 或表達式:
表達式參考上邊的介紹的UEL
表達式,這裏主要介紹監聽類使用。
定義任務監聽類,且類必須實現org.activiti.engine.delegate.TaskListener
接口
public class MyTaskListener implements TaskListener {
@Override
public void notify(DelegateTask delegateTask) {
//這裏指定任務負責人
delegateTask.setAssignee("張三");
}
}
使用監聽器分配方式,按照監聽事件去執行監聽類的
notify
方法,方法如果不能正常執行也會影響任務的執行。
Class
類需要指定到實現 org.activiti.engine.delegate.TaskListener
的具體類上,但一般使用較少,使用UEL表達式較多。
查詢任務
查詢任務負責人的待辦任務:
// 查詢當前個人待執行的任務
@Test
public void findPersonalTaskList() {
// 流程定義key
String processDefinitionKey = "holiday";
// 任務負責人
String assignee = "張三丰";
// 創建TaskService
TaskService taskService = processEngine.getTaskService();
List<Task> list = taskService.createTaskQuery()//
.processDefinitionKey(processDefinitionKey)//
.includeProcessVariables().taskAssignee(assignee).list();
for (Task task : list) {
System.out.println("----------------------------");
System.out.println("流程實例id:" + task.getProcessInstanceId());
System.out.println("任務id:" + task.getId());
System.out.println("任務負責人:" + task.getAssignee());
System.out.println("任務名稱:" + task.getName());
}
}
關聯 businessKey
在 activiti
實際應用時,查詢待辦任務可能要顯示出業務系統的一些相關信息.
比如:查詢待審批請假單任務列表需要將請假單的日期、請假天數等信息顯示出來,請假天數等信息在業務系統中存在,而並沒有在 activiti
數據庫中存在,所以是無法通過 activiti
的 api
查詢到請假天數等信息。
實現:
在查詢待辦任務時,通過businessKey
(業務標識 )關聯查詢業務系統的請假單表,查詢出請假天數等信息。
辦理任務
指定任務 id
,調用 TaskService
完成任務:
// 完成任務
@Test
public void completTask() {
//任務id
String taskId = "10305";
// 創建TaskService
TaskService taskService = processEngine.getTaskService();
Task task = taskService.createTaskQuery().taskId(taskId)
.taskAssignee(assignee).singleResult();
if(task != null){
taskService.complete(taskId);
System.out.println("完成任務");
}
}
注意:在實際應用中,完成任務前需要校驗任務的負責人是否具有該任務的辦理權限。