張超 王萌 任女爾
摘要:近年來,工作流技術(shù)日益成熟,會簽在流程系統(tǒng)中的出現(xiàn)也越來越頻繁。各大流程引擎也對會簽做了默認(rèn)支持。Activiti作為現(xiàn)今十分流行的開源流程引擎,通過多實例任務(wù)節(jié)點也對會簽做了支持,但是對多實例的回退卻沒做支持。為解決上述問題,該文通過Activiti提供的服務(wù)接口,并結(jié)合一定的算法,實現(xiàn)多實例任務(wù)的回退。
關(guān)鍵詞:工作流;Activiti;多實例;回退
中圖分類號:TP311 文獻標(biāo)識碼:A 文章編號:1009-3044(2018)19-0113-03
伴隨著信息化技術(shù)的高速發(fā)展,企業(yè)信息化也得以逐漸深入,普通的辦公自動化系統(tǒng)已經(jīng)無法滿足日漸增多的企業(yè)流程需求。會簽作為工作流程中的一種常見的場景,可以讓多個人相互協(xié)同,共同完成某一個任務(wù),因而在流程的信息傳遞上更加自動化,在流程的信息處理上更加高效,在任務(wù)的完成上更加直觀。所以會簽使用的時間成本更低,安全性、封閉性更高,相應(yīng)的,效率也就更高。
Activiti通過使用多實例任務(wù)節(jié)點,在業(yè)務(wù)流程中定義重復(fù)環(huán)節(jié),從而實現(xiàn)對會簽的支持。多實例任務(wù)節(jié)點通過給定的集合,對集合中的每一個元素執(zhí)行一次任務(wù),既可以順序同步執(zhí)行,也可以并發(fā)同時執(zhí)行這些任務(wù)。然后通過設(shè)置完成多實例任務(wù)的條件,決定會簽的后續(xù)走向。但是對于某些業(yè)務(wù)場景,多實例任務(wù)節(jié)點并不能滿足需求。比如:會簽中的某個參與者發(fā)現(xiàn)自己沒有參與會簽的資格,造成該現(xiàn)象的原因可能是在選擇會簽人員時的疏忽。
針對該業(yè)務(wù)場景,本文對Activiti的多實例任務(wù)進行了擴展和延伸,使得會簽任務(wù)中的某一個子任務(wù)得以有修正的機會,從而降低出錯率,避免整個會簽任務(wù)的失敗。
1 技術(shù)簡介
1.1 Workflow
1993年工作流管理聯(lián)盟(Workflow Management Coalition,WfMC)成立,作為工作流管理的標(biāo)準(zhǔn)化組織,對工作流給出了定義:工作流是指一類能夠完全自動執(zhí)行的經(jīng)營過程,根據(jù)一系列過程規(guī)則,將文檔、信息或任務(wù)在不同的執(zhí)行者之間進行傳遞與執(zhí)行。通俗點將,工作流是將一組任務(wù)以及任務(wù)相關(guān)的人組織起來以共同完成某一個業(yè)務(wù)過程。它定義了任務(wù)的順序以及后續(xù)任務(wù)的出發(fā)條件,每個任務(wù)可以由一個人來完成,也可以由多個人協(xié)同完成。
工作流引擎指的是Workflow應(yīng)該作為應(yīng)用系統(tǒng)的一部分,并為之提供解決方案,這些方案包括:根據(jù)分工和條件的不同以及角色來決定信息傳遞路由、內(nèi)容等級等核心解決方案。工作流引擎包含了流程圖的繪制、流程節(jié)點的管理、流程流向的控制以及流程實例的管理等。目前市面上常見的流程引擎主要包含:JBPM、Activiti、SWF等。
1.2 Activiti
Activiti項目是一個開源的BPM平臺,提供了對BPMN2.0標(biāo)準(zhǔn)的支持。Activiti是一種BPM引擎,它輕量,并且可嵌入。為了可以被廣泛使用,Activiti提供了寬松的Apache許可2.0。同時,為了促進和BPMN2.0標(biāo)準(zhǔn)的匹配,該項目由OMG通過標(biāo)準(zhǔn)審定。
Activiti項目的創(chuàng)始人之一Tom Baeyens,原先是JBoss jBPM的項目架構(gòu)師,因此,Activiti是基于JBPM4開發(fā)的,同時支持流程虛擬機技術(shù),并且對外提供了清洗的服務(wù)接口,可以很好地集成外部服務(wù)。關(guān)于Activiti的優(yōu)勢,Tom Baeyens曾說:“Activiti有非常大的影響力來改變目前BPM的生態(tài)。Activiti的Apache授權(quán),完整的功能,將使Activiti到達一個新的水平。Activiti將推動業(yè)界的創(chuàng)新,因為BPM技術(shù)可以廣泛而自由地被應(yīng)用。通過實現(xiàn)這些想法以及開源社區(qū)的努力,也讓Activiti成為事實上的 BPM和BPMN標(biāo)準(zhǔn)執(zhí)行”。SpringSource的首席技術(shù)官Adrian Coyler也說道:“這是一個對Spring開發(fā)人員和Java社區(qū)總體的發(fā)展非常令人興奮的事情,長期以來一直需要一個Apache許可的流程引擎,這對許多應(yīng)用系統(tǒng)非常實用的需求。我們認(rèn)為,Activiti作為新的應(yīng)用領(lǐng)域擴展到的Java和開源的發(fā)展,特別是在云架構(gòu)上”。
2 系統(tǒng)架構(gòu)
本課題涉及項目的軟件技術(shù)架構(gòu)使用JAVA語言,采用B/S架構(gòu),綜合SpringBoot、Hibernate、Shiro等框架進行業(yè)務(wù)邏輯開發(fā),采用Activiti工作流引擎處理業(yè)務(wù)流程,頁面則采用Html、Bootstrap、Ajax開發(fā)。整體系統(tǒng)架構(gòu)如下所示:
本系統(tǒng)底層操作系統(tǒng)支持Windows、linux、Solaris等操作系統(tǒng),數(shù)據(jù)庫采用Oracle;在此基礎(chǔ)之上,通過JDBC與數(shù)據(jù)庫交互,通過XML和properties文件進行緩存、日志等的配置;上層數(shù)據(jù)層采用Hibernate和Spring提供的方法設(shè)計數(shù)據(jù)庫相關(guān)操作;業(yè)務(wù)層在數(shù)據(jù)庫操作的基礎(chǔ)之上對業(yè)務(wù)邏輯進行處理;控制層通過SpringMVC使得業(yè)務(wù)邏輯與前端UI系統(tǒng)進行交互,前端UI系統(tǒng)由html和jQuery, bootstrap,進行表現(xiàn)層的展示。系統(tǒng)嚴(yán)格按照MVC架構(gòu)模式進行設(shè)計和開發(fā),如下圖所示:
2.1 多實例任務(wù)回退的設(shè)計與實現(xiàn)
2.1.1 設(shè)計思想
多實例任務(wù)回退的設(shè)計思想是當(dāng)多實例任務(wù)中的某個子任務(wù)要回退時,首先將該任務(wù)的處理人置空,這樣要回退的任務(wù)就不會出現(xiàn)在待辦列表里,也就不會被某個人完成,流程就會停留在多實例節(jié)點處,再通過利用Activiti提供的服務(wù)接口TaskService中的兩個方法:TaskService.newTask()和TaskService.saveTask()來創(chuàng)建回退的任務(wù)并保存到數(shù)據(jù)庫,由于創(chuàng)建的新任務(wù)不能關(guān)聯(lián)到某個具體的流程,所以這里采用一種折中的辦法:在任務(wù)的本地變量里設(shè)置相關(guān)的信息,同時添加兩個變量:MULTI_INSTANCE_ROLLBACK_和INSTANCE_ROLLBACK_ID_,分別表示新任務(wù)是一個多實例的回退任務(wù)以及原始任務(wù)ID,這樣,新任務(wù)就和原始任務(wù)有了關(guān)聯(lián),完成任務(wù)時,就可以重新指定子任務(wù)的處理人了。
2.1.2 具體實現(xiàn)過程及相關(guān)代碼
1) 流程設(shè)計圖
在IDEA開發(fā)工具中,使用流程繪制插件按照BPMN2.0規(guī)范繪制流程圖,流程圖中包含一個多實例任務(wù)節(jié)點,流程文件部分代碼如下:
2) 將設(shè)計好的流程部署,因為使用的springboot,將流程定義文件放置到src/main/resources/processes目錄下,項目啟動時會自動部署。
3) 部署后就可以使用流程了。首先要發(fā)起一個流程實例,并設(shè)置流程發(fā)起人,代碼如下:
ProcessInstance processInstance = null;
try {
identityService.setAuthenticatedUserId("user1");
processInstance = runtimeService.startProcessInstanceByKey("MyMultiInstanceRollbackProcess");
}finally {
identityService.setAuthenticatedUserId(null);
}
發(fā)起流程后,就可以獲取相應(yīng)的待辦,并完成任務(wù)。首先,我們獲取用戶user1的待辦任務(wù),并完成,在完成的時候指定下一個多實例任務(wù)的集合,代碼如下:
Task user1Task = taskService.createTaskQuery().taskAssignee("user1").singleResult();
Map
String[] assignees = {"user21","user22","user23"};
variables.put("assigneeCollection",Arrays.asList(assignees));
taskService.complete(user1Task.getId(),variables);
4) 簽收并完成任務(wù)。先讓use22和user23完成任務(wù),代碼如下:
Task user22Task = taskService.createTaskQuery().taskAssignee("user22").singleResult();
taskService.complete(user22Task.getId());
Task user23Task = taskService.createTaskQuery().taskAssignee("user23").singleResult();
taskService.complete(user23Task.getId());
5) 回退多實例任務(wù)。user21查看到待辦任務(wù)后,發(fā)現(xiàn)該任務(wù)不應(yīng)該是自己處理的,于是回退給user1,代碼如下:
Task user21Task = taskService.createTaskQuery().taskAssignee("user21").singleResult();
taskService.setAssignee(user21Task.getId(),null);
Task rollbackTask = taskService.newTask();
rollbackTask.setAssignee("user1");
Map
rollbackTaskVariablesLocal.put("MULTI_INSTANCE_ROLLBACK_",true);
rollbackTaskVariablesLocal.put("INSTANCE_ROLLBACK_ID_",user21Task.getId());
taskService.saveTask(rollbackTask);
taskService.setVariablesLocal(rollbackTask.getId(),rollbackTaskVariablesLocal);
6) user1重新分配任務(wù)
user1Task = taskService.createTaskQuery().taskAssignee("user1").singleResult();
Map
if(user1TaskVariablesLocal.containsKey("MULTI_INSTANCE_ROLLBACK_")){
boolean isRollbackTask = (boolean)user1TaskVariablesLocal.get("MULTI_INSTANCE_ROLLBACK_");
if(isRollbackTask){
String originalTaskId = (String)user1TaskVariablesLocal.get("INSTANCE_ROLLBACK_ID_");
if(StringUtils.isEmpty(originalTaskId)){
throw new Exception("the multi instance rollback task has no original task");}
taskService.setAssignee(originalTaskId,"user24"); }}
7) 新分配的用戶查看待辦并完成任務(wù),代碼如下:
Task user24Task = taskService.createTaskQuery().taskAssignee("user24").singleResult();
taskService.complete(originalTaskId);
historyService.deleteHistoricTaskInstance(originalTaskId);
8) 會簽任務(wù)結(jié)束,流程繼續(xù)
3 結(jié)論
本文利用Activiti技術(shù)并結(jié)合一定的算法實現(xiàn)了多實例會簽任務(wù)的回退,為多實例任務(wù)分發(fā)錯誤的情況提供了解決方案。這個方案通過使用Activiti自身提供的API,并結(jié)合任務(wù)的本地變量,從而擴展了Activiti的多實例任務(wù),讓分發(fā)錯誤的子實例得以修正,同時還不影響其他正確的子實例。但是由于時間、精力、知識水平的制約,本設(shè)計也有需要提高的地方,例如由于使用了變量,導(dǎo)致變量表的快速增加,對查詢性能存在影響。后續(xù)可以考慮將這些變量的內(nèi)容單獨存在一張表中。
參考文獻:
[1] 范玉順.工作流管理技術(shù)基礎(chǔ)[M].北京:清華大學(xué)出版社,2001.
[2] 閆洪磊.Activiti實戰(zhàn)[M].北京:機械工業(yè)出版社,2014.
[3] 顧大明.基于JBPM的工作流會簽設(shè)計[J].民營科技,2010(12).
[4] 羅海濱,范玉順,吳澄.工作流技術(shù)綜述[J].軟件學(xué)報,2000,11(7):899-907.
[5] 梅峰,于洋,衛(wèi)青延,等.基于開源工作流 Activiti的企業(yè)協(xié)同信息平臺研究[J].福建電腦,2012(11):125-127.
[6] 張利君,馬駿,楊濤,等.基于工作流的動態(tài)任務(wù)調(diào)度研究與實現(xiàn)[J].計算機工程與設(shè)計,2009(10):2533-2537.
[7] 王安慧,孫長銀.管理信息系統(tǒng)會簽管理模塊的設(shè)計與應(yīng)用[J].三峽大學(xué)學(xué)報,2001,23(5):454-457.
[8] 馮天佑,梁立宇,李成華,等.基于Activiti工作流引擎技術(shù)的電力行業(yè)業(yè)務(wù)流程管理系統(tǒng)[J].信息通信,2013(8):57-59.
[9] Chen W.Enterprise information management system basedon J2EE and MVC mode[C]//Proceedings of the 9th In-ternational Symposium on Linear Drives for Industry Appli-cations.2014,3:427-433.
[10] 薛華成.管理信息系統(tǒng)[M].北京:清華大學(xué)出版社,1993.
[11] WFMC-TC-1025,工作流過程定義接口———XML 過程定義語言[S].
[12] 阿斯特.作流管理:模型、方法和系統(tǒng)[M].王建民,譯.北京:清華大學(xué)出版社,2004.
[13] 葉小路,錢真坤.基于 Activiti5 的水司OA系統(tǒng)設(shè)計與實現(xiàn)[J].軟件導(dǎo)刊,2013,12(6):93-95.
[14] Alexander Grosskopf,Gero Decker,Mathias Weske. The Process Business Process Modeling Using BPMN[M].Meghan-Kiffer Press,2009.