前些天在群里聊工作流和Activiti,群里有人分享了自己的工作流引擎開源項目,大伙紛紛問這問那(比如為什么突然自己搞個process engine、有沒有eclipse plugin、能不能繪制流程圖等等)。
現實生活中的工作流程,我們也經常碰到需要會簽的情況,支持會簽是很必要的。
正好有兩個人問道:支持會簽嗎? 也有人也問道:什么是會簽?
如果從process engine的角度上講呢?
可以說一個task節點下有多個task instance。
而不是一個從task節點執行到多個task節點(這樣就是ParallelGateway了)。
如何讓一個Task節點創建出多個instance?官網是這樣說的:
To make an activity multi-instance, the activity xml element must have a multiInstanceLoopCharacteristics child element.
既然是創建多個實例,我們就需要用一個集合去存放。
我們可以在multiInstanceLoopCharacteristics
標簽中加入一個attribute —— activiti:collection=""。
該attribute的值是當前流程實例的變量名,也就是啟動該引擎實例時傳入的Map的key。
而這個Map的value必須是java.util.List
類型的。但我們無需在意這個List的泛型是什么。
假如泛型是String的話,act_ru_variable
中變量的TYPE_
字段值是string。
也許我可以讓泛型是Map,那么該變量的TYPE_字段值是serialize,僅此而已。
本文中activiti:collection="assigneeList"
我們在數據庫里記錄了這個集合,但我們也需要記錄這個記錄中的每一個元素。
記錄每一個元素時他們的名字應該是什么?
我們可以用activiti:elementVariable=""
比如我設置:
activiti:elementVariable="assignee"
假設我們現在要的效果是:有三個人可以會簽,但只要兩個人簽署便可通過。
我們需要設置特定的條件來結束當前這個task。
這時我們需要在multiInstanceLoopCharacteristics下增加一個子節點——completionCondition
。
比如我是這樣設置的:
<completionCondition>
${signCount >= 2 }
</completionCondition>
好了,這樣就是整個Task的定義了。(事實上我完全可以不用signCount實現這個效果。)
<userTask id="counterTask_1" name="COUNTERTASK">
<multiInstanceLoopCharacteristics
isSequential="false"
activiti:collection="assigneeList"
activiti:elementVariable="assignee">
<completionCondition>${signCount >= 2 }</completionCondition>
</multiInstanceLoopCharacteristics>
</userTask>
部署后的結果如下:
此處省略部署流程的操作,我們來看一下如何申請該流程。
如下我在頁面中定義了三個審核人員:
<label>
<input type="checkbox" name="assigneeList" value="kim"/>kim
</label>
<label>
<input type="checkbox" name="assigneeList" value="jin"/>jin
</label>
<label>
<input type="checkbox" name="assigneeList" value="king"/>king
</label>
然后在java中接收並start:
private String[] assigneeList;
Map<String, Object> processInstVar = new HashMap<String, Object>();
//必須是List
processInstVar.put("assigneeList", Arrays.asList(assigneeList));
processInstVar.put("signCount", 0);
runtimeService.startProcessInstanceById(processId, processInstVar);
啟動結果如下:
然后是執行,method只接收一個taskId:
List<Task> taskResultList = taskService.createTaskQuery().taskId(taskId)
.list();
//當前executionId
String currentExecutionId = taskResultList.get(0).getExecutionId();
//當前簽署總數
String currentSignCount = StringUtils.defaultString(runtimeService
.getVariable(currentExecutionId, "signCount").toString(), "0");
//簽署數+1
runtimeService.setVariable(currentExecutionId, "signCount",
Integer.parseInt(currentSignCount) + 1);
//完成
taskService.complete(taskId);
我們執行了剛才創建的三個實例之一,結果是:
再執行一次,會簽節點的實例已經不存在於actrutask表了,因為我設置的是“有兩個人簽署便通過”。
如下圖,當前task已經不是會簽的task了,相關的變量也消失不見了。
最后說我之前為什么說道‘事實上我完全可以不用signCount實現這個效果’,因為我們有:
所以我完全沒有必要自己去定義一個變量去記錄執行了多少次