在Activiti實戰03_Hello World中我們介紹了一箇中間沒有任何任務的流程,實現了流程的部署與查閱,而在本章中,將會爲流程添加任務節點,是流程能夠像個流程,變得更加豐滿起來。
在上一節的基礎上,我門將會爲流程添加實際業務使其能夠正常工作起來,先模擬一個很簡單的請假流程。
首先,在上一節的流程圖中爲流程添加一個用戶任務(userTask)來處理申請,根據申請內容來決定運行申請還是駁回申請。流程圖如下:
代碼清單,由於篇幅的原因,這裏就不在列出任務的座標位置等信息
<?xml version="1.0" encoding="UTF-8"?> <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test"> <process id="myProcess" name="My process" isExecutable="true"> <startEvent id="startevent1" name="Start"></startEvent> <userTask id="deptLeaderAudit" name="領導審批" activiti:candidateGroups="deptLeader"></userTask> <sequenceFlow id="flow1" name="to User Task" sourceRef="startevent1" targetRef="deptLeaderAudit"></sequenceFlow> <scriptTask id="outputAuditResult" name="輸出審批結果" scriptFormat="groovy" activiti:autoStoreVariables="false"> <script>out:println "applyUser:" + applyUser +" ,days:"+ days +",approval:" + approved;</script> </scriptTask> <sequenceFlow id="flow2" name="to Script Task" sourceRef="deptLeaderAudit" targetRef="outputAuditResult"></sequenceFlow> <endEvent id="endevent1" name="End"></endEvent> <sequenceFlow id="flow3" name="to End" sourceRef="outputAuditResult" targetRef="endevent1"></sequenceFlow> </process> </definitions>
簡單說一下這個代碼清單裏值得注意的地方,首先增加了兩個任務節點,即<userTask></userTask>標籤和<scriptTask></scriptTask>標籤中所包含的內容,因爲有四個節點,自然會產生三條連線,即<sequenceFlow></sequenceFlow>之間的內容,id分別爲flow1,flow2,fow3,,對於scriptTask而言,因爲採用了groovy的語法,所以需要導入相關jar包或添加相關依賴。
<dependency> <groupId>org.codehaus.groovy</groupId> <artifactId>groovy-all</artifactId> <version>2.4.7</version> </dependency>
測試:
代碼清單
public class SimpleLeaveProcessTest { @Test public void testStartProcess(){ // 創建流程引擎,使用內存數據庫 ProcessEngine processEngine = ProcessEngineConfiguration .createStandaloneInMemProcessEngineConfiguration() .buildProcessEngine(); // 部署流程定義文件 RepositoryService repositoryService = processEngine.getRepositoryService(); repositoryService.createDeployment() .addClasspathResource("diagrams/SimpleLeave.bpmn") .deploy(); // 驗證已部署的流程定義 ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() .singleResult(); assertEquals("myProcess",processDefinition.getKey()); // 啓動流程並返回流程實例 RuntimeService runtimeService = processEngine.getRuntimeService(); //設置流程變量 Map<String, Object> variables = new HashMap<String,Object>(); variables.put("applyUser", "employee1"); variables.put("days", 3); //帶着流程變量開啓流程 ProcessInstance instance = runtimeService.startProcessInstanceByKey("myProcess",variables); assertNotNull(instance); System.out.println("pid = " +instance.getId() +", pdid = " + instance.getProcessDefinitionId() ); //獲取任務服務 TaskService taskService = processEngine.getTaskService(); //獲取領導審批任務 Task taskOfDeptLeader = taskService.createTaskQuery() .taskCandidateGroup("deptLeader") .singleResult(); assertNotNull(taskOfDeptLeader); //驗證任務是否爲領導審批任務 assertEquals("領導審批", taskOfDeptLeader.getName()); //作爲有權處理的組角色,拾取任務,此時相同角色的其他人便看不到該任務了 taskService.claim(taskOfDeptLeader.getId(), "leaderUser"); variables = new HashMap<String,Object>(); // 再次設置流程變量 variables.put("approved", true); // 帶着流程變量完成任務 taskService.complete(taskOfDeptLeader.getId(),variables); // 由於任務已經完成,所以不再是改組角色擁有的任務,此時就查不到任務了 taskOfDeptLeader = taskService.createTaskQuery() .taskCandidateGroup("deptLeader") .singleResult(); assertNull(taskOfDeptLeader); // 任務已經走完就會歸到歷史裏面,所以這裏從歷史中查數據 HistoryService historyService = processEngine.getHistoryService(); long count = historyService.createHistoricProcessInstanceQuery() .finished() .count(); //判斷是否有一個任務已完成,並處於歷史狀態 assertEquals(1, count); } }
代碼解釋:
在上一章中,我們是直接開啓了流程,然後就直接走向了結束。在這章中,因爲存在任務節點的關係,一旦開啓流程,便會走到任務節點處,此處就是【領導審批】任務節點,而這次開啓流程的方式也和上一章有所不同,這章是帶着流程變量開啓的流程,上一章則是直接開啓流程,至於流程變量是什麼,你可以這樣理解,就好比你去菜市場買魚,走了好幾家,挑了好幾條,終於挑到了一條讓自己滿意的魚了,然後就高高興興的帶着魚回家了,在Activiti中,流程變量也是一樣的,只要是同名的流程變量,便會採用頂替的原則,就好比你挑了好幾條一樣,每次只是替換,並不改變魚這個種類,然後只有最後一次的有效,無論中間發生了多少次改變(前提是在你用這個流程變量之前的最後一次改變)。說完了流程變量,我們也開啓了流程,接下來因爲用戶任務的存在,所以流程會阻塞在用戶任務那裏,直到有人接收並處理了任務,纔會轉到下一步(依照目前的流程圖是這樣的),存在一個用戶拾取了任務,並完成了任務,就會繼續往下走,由於是腳本任務,所以在執行完後流程就直接結束了,就只能從歷史中查了。至此,一個簡單的請假流程就算是完成了。