JBPM具體應用之流程變數與任務變數
在上一篇文章《淺析JBPM工作流引擎》中我們介紹了什麼是JBPM,以及一個簡單的JBPM例項,並且我們知道了一個jpdl檔案實際上就是一個業務流程,每一個流程例項就是這個業務流程的例項化,而在每一個流程中又可以有多個任務,而無論是在是流程例項中還是具體的任務中,由於業務的需要都不可避免的要使用到變數,我們分別稱之為流程變數和任務變數,那流程變數和任務變數具體是怎樣應用的,他們有什麼區別等問題我將分別作具體的介紹。
首先來看我們的業務流程:
<?xml version="1.0" encoding="UTF-8"?> <process name="test" key="test" xmlns="http://jbpm.org/4.4/jpdl"> <start name="start1" g="275,16,48,48"> <transition name="而提交到科長審批" to="科長審批" g="-110,-15"/> </start> <task assignee="張三" name="科長審批" g="255,101,92,52"> <transition name="提交到主任" to="主任審批" g="-69,-20"/> </task> <task assignee="李四" name="主任審批" g="259,186,92,52"> <transition name="通過" to="end1" g="-50,-20"/> </task> <end name="end1" g="283,283,48,48"/> </process>
通過jpdl檔案我們可以看出這個業務流程仍然非常的簡單,就是一個簡單的任務傳遞過程。當建立好一個流程例項的時候首先進入的是“科長審批”節點,執行人是“張三”,當張三完成任務後,提交給任務人李四,李四執行“主任審批”任務,執行完畢後結束整個流程。介紹完業務流程後我們通過java程式碼介紹流程變數和任務變數的具體應用和區別。
後臺程式碼結構主要有三部分,第一個為父類JbpmTestCase,第二個為介面JbpmUtil,第三個為子類TestVariable,子類繼承父類並實現介面。
父類JbpmTestCase中startUp()方法的作用主要是注入各種服務,省去了子類每次都要手動建立服務的麻煩,而介面主要是為了保證每個子類都至少具有上文提到的五分部。在這裡我們主要來看子類程式碼:
/** * 流程變數 * @author yang * */ public class TestVariable extends JbpmTestCase implements JbpmUtil { //部署流程 public void deploy() { super.startUp(); repositoryService.createDeployment().addResourceFromClasspath("test.jpdl.xml").deploy(); } //建立流程例項 public void createInstance() { super.startUp(); Map<String,Object> variable = new HashMap<String, Object>(); variable.put("userId", "001"); variable.put("userName", "tom"); ProcessInstance processInstance = executionService.startProcessInstanceByKey("mytest", variable); super.print("流程例項ID", String.valueOf(processInstance.getId())); } //取得特定例項的當前任務節點 public void getCurrentActivity() { ProcessEngine processEngine = Configuration.getProcessEngine(); ExecutionService executionService = processEngine.getExecutionService(); String activityName = executionService.createProcessInstanceQuery().processInstanceId("mytest.10001").uniqueResult().findActiveActivityNames().toString(); System.out.println("當前任務所在節點======" + activityName); } //取得對應人員的第一個任務 public void getTask() { ProcessEngine processEngine = Configuration.getProcessEngine(); TaskService taskService = processEngine.getTaskService(); List<Task> tasks = taskService.findPersonalTasks("張三"); Task task = tasks.get(0); System.out.println("任務數量===" + tasks.size() ); System.out.println("任務名詞===" + task.getActivityName()); System.out.println("任務人員===" + task.getAssignee() + "任務ID===" + task.getId()); } //根據任務ID完成任務 public void completeTask() { super.startUp(); taskService.completeTask("10004"); } //新增任務變數 public void addTaskVariable(){ super.startUp(); Map<String ,Object> map = new HashMap<String,Object>(); map.put("taskUserId", "100"); map.put("taskUserName","jack"); taskService.setVariables("10004", map); } //取得任務變數 public void getTaskVariable(){ super.startUp(); String taskUserId = taskService.getVariable("10004", "taskUserId").toString(); String taskUserName = taskService.getVariable("10004", "taskUserName").toString(); print("taskUserId",taskUserId); print("taskUserName",taskUserName); } //取得流程變數 public void getMyVariable(){ super.startUp(); String userId = executionService.getVariable("mytest.10001", "userId").toString(); String userName = executionService.getVariable("mytest.10001", "userName").toString(); this.print("userId", userId); this.print("userName", userName); } //更新流程變數 public void updateMyVariable(){ super.startUp(); executionService.setVariable("test.90001", "userId", "002"); } //查詢某流程所有流程變數的名稱和值 public void findMyVariable(){ super.startUp(); Set<String> set = executionService.getVariableNames("test.90001"); Iterator iter = set.iterator(); while(iter.hasNext()){ System.out.println(iter.next()); } Map<String ,Object> map = executionService.getVariables("test.90001", set); Iterator it = map.entrySet().iterator(); while(it.hasNext()){ Map.Entry m = (Map.Entry)it.next(); this.print(m.getKey().toString(), m.getValue().toString()); } } }
(1) 執行deploy()函式部署一個業務流程。
(2) 執行 createInstance()函式建立一個流程例項,在建立流程例項的同時建立了兩個流程變數,變數名分別為“userId”和“userName”,變數值分別為“001”和“tom”。並且得到了流程例項ID為“mytest.10001”,此時這兩個變數就和這個例項綁定了,也就是說這兩個變數只屬於ID為“mytest.10001”的流程例項。
(3) 執行getTask(),取得當前任務的任務ID為“10004”。
(4) 執行addTaskVariable()函式,給“10004”任務新增兩個任務變數,變數名分為“taskUserId”和“taskUserName”,值分別為“100”和“jack”。
到上一步為止我們新增好了流程變數和任務變數,現在我們來執行getMyVariable()函式來取得流程例項ID為mytest.10001變數名為“userId”和“userName”的變數值。通過控制檯我們可以看到能夠取出流程例項變數。
(5) 執行getMyVariable()函式我們可以看到能夠取出流程變數的值。
(6) 執行completeTask()完成任務ID為10004的任務。
(7) 再次執行getMyVariable(),我們可以看到仍然可以取得流程變數“userId”和“userName”的值。
(8) 再次執行getTaskVariable(),我們可以看到此時已經不能取得任務變數的值。
分析:流程例項變數和任務變數的關係我們可以用下圖表示:
從上圖中我們可以看出流程變數和任務變數一個最明顯的區別是他們的作用域不同,流程變數的作用於是整個流程例項,而任務變數的作用於僅僅是它所在的任務。所以在我們第一次執行getMyVariable()和getTaskVariable()既能夠取得流程變數又能夠取得任務變數是因為流程沒有結束,任務也沒有結束,而第二次能夠取得流程變數卻不能取得任務變數,是因為我們雖然結束了“10004”任務,但是流程會進入第二個“主任審批”任務,也就是說“10004”科長審批任務雖然結束了,但是流程並沒有結束,所以會出現上面的情況,如果我們再結束主任審批任務,可以執行一次getMyVariable()函式,肯定連流程變數也取不到了。綜上所述,任務變數和流程變數能不能取得關鍵要看流程或任務是否結束,只要沒有結束就一定可以取出,反之當任務(流程結束)的時候,任務變數(流程變數)也隨任務(流程)的結束而銷燬。至於更新流程變數和取得某個流程所有的流程變數有興趣的可以看一下本文不做重點介紹。