BPM(Business Process Management)——“通過建模、自動化、管理和優(yōu)化流程,打破跨部門跨系統(tǒng)業(yè)務(wù)過程依賴,提高業(yè)務(wù)效率和效果”。
Workflow——“全部或者部分由計算機支持或自動處理的業(yè)務(wù)過程”(工作流管理聯(lián)盟WfMC組織對工作流概念的經(jīng)典定義)
BPM基本內(nèi)容是管理既定工作的流程,通過服務(wù)編排,統(tǒng)一調(diào)控各個業(yè)務(wù)流程,以確保工作在正確的時間被正確的人執(zhí)行,達到優(yōu)化整體業(yè)務(wù)過程的目的。BPM概念的貫徹執(zhí)行,需要有標(biāo)準(zhǔn)化的流程定義語言來支撐,使用統(tǒng)一的語言遵循一致的標(biāo)準(zhǔn)描述具體業(yè)務(wù)過程,這些流程定義描述由專有引擎去驅(qū)動執(zhí)行。這個引擎就是工作流引擎,它作為BPM的核心發(fā)動機,為各個業(yè)務(wù)流程定義提供解釋、執(zhí)行和編排,驅(qū)動流程“動“起來,讓大家的工作“流”起來,為BPM的應(yīng)用提供基本、核心的動力來源。
現(xiàn)實工作中,不可避免的存在跨系統(tǒng)跨業(yè)務(wù)的情況,而大部分企業(yè)在信息化建設(shè)過程中是分階段或分部門(子系統(tǒng))按步實施的,后期實施的基礎(chǔ)可能是前期實施成果的輸出,在耦合業(yè)務(wù)實施階段,相同的業(yè)務(wù)過程可能會在不同的實施階段重用,在進行流程梳理過程中,不同的實施階段所使用的流程描述語言或遵循的標(biāo)準(zhǔn)會有所不同(服務(wù)廠商不同),有的使用WfMC的XPDL,還有些使用BPML、BPEL、WSCI等,這就造成流程管理、業(yè)務(wù)集成上存在很大的一致性、局限性,提高了企業(yè)應(yīng)用集成的成本。
遵循BPMN2.0新規(guī)范的工作流產(chǎn)品能很大程度上解決此類問題。BPMN2.0相對于舊的1.0規(guī)范以及XPDL、BPML及BPEL等最大的區(qū)別是定義了規(guī)范的執(zhí)行語義和格式,利用標(biāo)準(zhǔn)的圖元去描述真實的業(yè)務(wù)發(fā)生過程,保證相同的流程在不同的流程引擎得到的執(zhí)行結(jié)果一致。BPMN2.0對流程執(zhí)行語義定義了三類基本要素,它們是日常業(yè)務(wù)流程的“三板斧”:
這三類執(zhí)行語義的定義涵蓋了業(yè)務(wù)流程常用的Sequence Flow(流程轉(zhuǎn)向)、Task(任務(wù))、Sub-Process(子流程)、Parallel Gateway(并行執(zhí)行網(wǎng)關(guān))、ExclusiveGateway(排它型網(wǎng)關(guān))、InclusiveGateway(包容型網(wǎng)關(guān))等常用圖元,如圖1:
圖1:BPMN2.0三類基本執(zhí)行語義要素
現(xiàn)實業(yè)務(wù)所有的業(yè)務(wù)環(huán)節(jié)都離不開Activities、Gateways和Events,無論是簡單的條件審批還是復(fù)雜的父子流程循環(huán)處理,在一個流程定義描述中,所有的業(yè)務(wù)環(huán)節(jié)都離不開Task、Sequence Flow、Exclusive Gateway、Inclusive Gateway(如圖1中右側(cè)綠色標(biāo)記所示元素),其中Task是一個極具威力的元素,它能描述業(yè)務(wù)過程中所有能發(fā)生工時的行為,它包括User Task、Manual Task、Service Task、Script Task等,可以被用來描述人機交互任務(wù)、線下操作任務(wù)、服務(wù)調(diào)用、腳本計算任務(wù)等常規(guī)功能。
User Task:生成人機交互任務(wù),主要被用來描述需要人為在軟件系統(tǒng)中進行諸如任務(wù)明細查閱、填寫審批意見等業(yè)務(wù)行為的操作,流程引擎流轉(zhuǎn)到此類節(jié)點時,系統(tǒng)會自動生成被動觸發(fā)任務(wù),須人工響應(yīng)后才能繼續(xù)向下流轉(zhuǎn)。常用于審批任務(wù)的定義。
Manual Task:線下人為操作任務(wù),常用于為了滿足流程圖對實際業(yè)務(wù)定義的完整性而進行的與流程驅(qū)動無關(guān)的線下任務(wù),即此類任務(wù)不參與實際工作流流轉(zhuǎn)。常用于諸如物流系統(tǒng)中的裝貨、運輸?shù)热蝿?wù)的描述。
Service Task:服務(wù)任務(wù),通常工作流流轉(zhuǎn)過程中會涉及到與自身系統(tǒng)服務(wù)API調(diào)用或與外部服務(wù)相互調(diào)用的情況,此類任務(wù)往往由一個具有特定業(yè)務(wù)服務(wù)功能的Java類承擔(dān),與User Task不同,流程引擎流經(jīng)此節(jié)點會自動調(diào)用Java類中定義的方法,方法執(zhí)行完畢自動向下一流程節(jié)點流轉(zhuǎn)。另外,此類任務(wù)還可充當(dāng)“條件路由”的功能對流程流轉(zhuǎn)可選分支進行自動判斷。常用于業(yè)務(wù)邏輯API的調(diào)用。
Script Task:腳本任務(wù),在流程流轉(zhuǎn)期間以“腳本”的聲明或語法參與流程變量的計算,目前支持的腳本類型有三種:juel(即JSP EL)、groovy和javascript。在Activiti5.9中新增了Shell Task,可以處理系統(tǒng)外部定義的Shell腳本文件,也與Script Task有類似的功能。常用于流程變量的處理。
BPMN2.0為所有業(yè)務(wù)元素定義了標(biāo)準(zhǔn)的符號,不同的符號代表不同的含義,以O(shè)A應(yīng)用中請假流程為例,使用標(biāo)準(zhǔn)的BPMN2.0圖元定義示意如圖2:
圖2:BPMN2.0請假流程定義
在上述的流程示意圖中,所涉及到的執(zhí)行語義圖元主要有表1中的8類:
表1:請假流程所用圖元
除了上述Start Event、User Task、Exclusive Gateway、Parallel Gateway、Service Task、End Event標(biāo)準(zhǔn)的BPMN2.0圖元外,上述流程圖還使用了Lane Set(業(yè)務(wù)部門、人力資源部、考勤系統(tǒng)),分別表示流程活動所涉及到的部門或角色,Lane的概念和jBPM4中“泳道”的概念一樣,都用來表示同一類相似任務(wù)的歸屬者。
應(yīng)用BPMN2.0標(biāo)準(zhǔn)的一個最顯著的特色是,不同階段的人員,無論是需求分析、概要設(shè)計、詳細設(shè)計或是具體的業(yè)務(wù)實現(xiàn),都可在一個流程圖上開展工作,避免業(yè)務(wù)理解存在偏差。一個系統(tǒng)的實現(xiàn),需求分析人員可以利用BPMN2.0標(biāo)準(zhǔn)圖元草繪一下搜集到的需求;然后可以拿給設(shè)計人員,討論出具體的業(yè)務(wù)需求進行功能設(shè)計,由設(shè)計人員在草圖的基礎(chǔ)上逐步細化,并得到需求人員的認同;設(shè)計人員又將細化后的流程圖交給開發(fā)人員,羅列要實現(xiàn)的功能點,指出流程圖上各活動節(jié)點所具備的行為,設(shè)計人員與開發(fā)人員依據(jù)此圖達成共識,進入具體的開發(fā)階段;如果后期請假流程發(fā)生更改,仍然是在現(xiàn)有流程圖上更改,隨著項目的推進,流程圖也在不斷的演進,但至始至終,項目受眾都使用同一個流程圖交流,保障需求理解的一致性,一定程度上推動了項目的敏捷性。
作為支持最新BPMN2.0規(guī)范的開源工作流引擎Activit5,實現(xiàn)了對規(guī)范的絕大多數(shù)圖元的定義,能夠滿足企業(yè)工作流的各種復(fù)雜應(yīng)用。它是一個無侵入的、支持嵌入式和獨立部署的開源工作流引擎,是Tom Bayen離開jBoss加入Alfresco公司后的另立山頭之作,共同開發(fā)Activit5的除了Alfresco外還有SpringSource、MuleSoft、Salves、FuseSource、Signavio等公司。從Activiti5.0到當(dāng)前的5.9(今年3月份發(fā)布),版本更新迭代速度很快,新版本功能穩(wěn)定,性能良好,為開源社區(qū)提供了商業(yè)工作流之外非常具有競爭力的選擇。
值得一提的是,Activiti5與jBPM5都屬于業(yè)界優(yōu)秀的開源工作流引擎,都支持BPMN2.0最新規(guī)范,均基于Apache License,符合J2EE規(guī)范,提供工作流建模、執(zhí)行以及對流程生命周期過程監(jiān)控。但兩者設(shè)計理念和技術(shù)組成卻有很大不同,見下表2:
序號 | 技術(shù)組成 | Activiti | jBPM |
1 | 數(shù)據(jù)庫持久層ORM | MyBatis3 | Hibernate3 |
2 | 持久化標(biāo)準(zhǔn) | 無 | JPA規(guī)范 |
3 | 事務(wù)管理 | MyBatis機制/Spring事務(wù)控制 | Bitronix,基于JTA事務(wù)管理 |
4 | 數(shù)據(jù)庫連接方式 | Jdbc/DataSource | Jdbc/DataSource |
5 | 支持?jǐn)?shù)據(jù)庫 | Oracle、SQL Server、MySQL等多數(shù)數(shù)據(jù)庫 | Oracle、SQL Server、MySQL等多數(shù)數(shù)據(jù)庫 |
6 | 設(shè)計模式 | Command模式、觀察者模式等 | |
7 | 內(nèi)部服務(wù)通訊 | Service間通過API調(diào)用 | 基于Apache Mina異步通訊 |
8 | 集成接口 | SOAP、Mule、RESTful | 消息通訊 |
9 | 支持的流程格式 | BPMN2、xPDL、jPDL等 | 目前僅只支持BPMN2 xml |
10 | 引擎核心 | PVM(流程虛擬機) | Drools |
11 | 技術(shù)前身 | jBPM3、jBPM4 | Drools Flow |
12 | 所屬公司 | Alfresco | jBoss.org |
表2:Activiti5與jBPM5技術(shù)組成
Activiti5使用Spring進行引擎配置以及各個Bean的管理,綜合使用IoC和AOP技術(shù),使用CXF作為Web Services實現(xiàn)的基礎(chǔ),使用MyBatis進行底層數(shù)據(jù)庫ORM的管理,預(yù)先提供Bundle化包能較容易的與OSGi進行集成,通過與Mule ESB的集成和對外部服務(wù)(Web Service、RESTful等)的接口可以構(gòu)建全面的SOA應(yīng)用;jBPM5使用jBoss.org社區(qū)的大多數(shù)組件,以Drools Flow為核心組件作為流程引擎的核心構(gòu)成,以Hibernate作為數(shù)據(jù)持久化ORM實現(xiàn),采用基于JPA/JTA的可插拔的持久化和事務(wù)控制規(guī)范,使用Guvnor作為流程管理倉庫,能夠與Seam、Spring、OSGi等集成。
需要指出的是Activiti5是在jBPM3、jBPM4的基礎(chǔ)上發(fā)展而來的,是原jBPM的延續(xù),而jBPM5則與之前的jBPM3、jBPM4沒有太大關(guān)聯(lián),且舍棄了備受推崇的PVM(流程虛擬機)思想,轉(zhuǎn)而選擇jBoss自身產(chǎn)品Drools Flow作為流程引擎的核心實現(xiàn),工作流最為重要的“人機交互”任務(wù)(類似于審批活動)則由單獨的一塊“Human Task Service”附加到Drools Flow上實現(xiàn),任務(wù)的查詢、處理等行為通過Apache Mina異步通信機制完成。
優(yōu)劣對比:
從技術(shù)組成來看,Activiti最大的優(yōu)勢是采用了PVM(流程虛擬機),支持除了BPMN2.0規(guī)范之外的流程格式,與外部服務(wù)有良好的集成能力,延續(xù)了jBPM3、jBPM4良好的社區(qū)支持,服務(wù)接口清晰,鏈?zhǔn)紸PI更為優(yōu)雅;劣勢是持久化層沒有遵循JPA規(guī)范。
jBPM最大的優(yōu)勢是采用了Apache Mina異步通信技術(shù),采用JPA/JTA持久化方面的標(biāo)準(zhǔn),以功能齊全的Guvnor作為流程倉庫,有RedHat(jBoss.org被紅帽收購)的專業(yè)化支持;但其劣勢也很明顯,對自身技術(shù)依賴過緊且目前僅支持BPMN2。
命令模式能將命令的發(fā)出與執(zhí)行分開,委派給不同的對象,每一個命令都代表一個指令,其最大的好處是提供了一個公共接口,使得用戶可以用同一種方式調(diào)用所有的事務(wù),同時也易于添加新事務(wù)以擴展系統(tǒng)。
Activiti5大量采用了命令模式,在流程運行期間,所有的指令執(zhí)行(比如流程部署、流程流轉(zhuǎn)、獲取任務(wù)等)都使用此模式實現(xiàn), 其中涉及到四個重要的概念:
Command:Activiti5的命令定義接口,僅有一個execute方法,所有運行期要執(zhí)行的指令都要實現(xiàn)該接口,定義要執(zhí)行的具體行為。
CommandContext:命令執(zhí)行的上下文環(huán)境,每個Command的執(zhí)行都依賴其上下文環(huán)境,CommandContext創(chuàng)建了命令執(zhí)行期間的引擎會話與數(shù)據(jù)庫會話,每個CommandContext都是一個單獨的ThreadLocal,執(zhí)行期間不會受其它線程干預(yù),是線程安全的。
CommandExecutor:命令執(zhí)行器,負責(zé)執(zhí)行所有的運行時Command。引擎中各項指令的執(zhí)行(即命令的產(chǎn)生者可能來源于多種對象)都托CommandExecutor處理,僅有一個接口方法:execute(Command
人機交互任務(wù)是業(yè)務(wù)流程應(yīng)用中最常用的業(yè)務(wù)類型,以BPMN2.0中定義的“Task”這個典型元素說明一下命令模式在Activiti5中的應(yīng)用:
Activiti5針對BPMN2.0的Task Element定義了Task接口,并依據(jù)Semantic.xsd執(zhí)行語義定義了相關(guān)任務(wù)元素所具有的行為特性,此行為特性通過setActivityBehavior方法進行行為與元素的綁定,這些Behavior在流程引擎驅(qū)動流轉(zhuǎn)到活動節(jié)點時將被觸發(fā),通過execute(ActivityExecution execution)執(zhí)行ActivityBehavior中指定的操作;
每個活動有若干個Command與之對應(yīng),比如ClaimTaskCmd、CompleteTaskCmd、DelegateTaskCmd、SaveTaskCmd、DeleteTaskCmd等,分別表示任務(wù)的領(lǐng)取、完成、轉(zhuǎn)交、保存、刪除等,這些操作指令的執(zhí)行結(jié)果通過命令執(zhí)行上下文(CommandContext)得到DAO層的TaskManager將任務(wù)對象的變更持久化到數(shù)據(jù)庫中;
引擎不關(guān)心要執(zhí)行什么,凡是實現(xiàn)了Command接口的類都可以通過CommandExecutor執(zhí)行,除了引擎提供的這些原生的任務(wù)指令外,如果業(yè)務(wù)系統(tǒng)有額外的特性化操作,也可以自定義一組Command,在Command.execute()中自由調(diào)用外部服務(wù)、發(fā)送手機短信、附加任務(wù)屬性、調(diào)用DAO操作數(shù)據(jù)庫等,封裝完畢后交由引擎去執(zhí)行,即可得到希望的結(jié)果。同樣,如果在業(yè)務(wù)系統(tǒng)中需要自定義BPMN元素或?qū)傩?,僅需同步增加ActivityBehavior接口的實現(xiàn),在解析流程定義文件時將自定義的行為實現(xiàn)與元素(屬性)幫定,并緩存之,待引擎驅(qū)動到達節(jié)點時自動執(zhí)行。在ActivityBehavior. execute()中依然可以調(diào)用各種各樣的API已實現(xiàn)特定的業(yè)務(wù)目的。
此處需要注意的是,Activiti5的CommandContext是包含事務(wù)處理的,在每次關(guān)閉上下文環(huán)境時,會執(zhí)行事務(wù)的提交,但在實際業(yè)務(wù)系統(tǒng)中,業(yè)務(wù)事務(wù)、引擎事務(wù)以及數(shù)據(jù)庫事務(wù)應(yīng)該是被統(tǒng)一到一個事務(wù)中去管理,這就需要將Activiti5的事務(wù)與業(yè)務(wù)系統(tǒng)的事務(wù)合并。Activiti5通過Spring注入提供了該方式的可行性,引擎內(nèi)部的事務(wù)控制可以委托給業(yè)務(wù)層去處理,在初始化引擎配置時,將業(yè)務(wù)系統(tǒng)中定義的DataSource和TransactionManager傳遞給流程配置的dataSource、transactionManager屬性后,Activiti5內(nèi)部會使用Spring提供的TransactionAwareDataSourceProxy來封裝傳進來的DataSource,并利用外部的事務(wù)管理來接管Activiti5的事務(wù)控制,確保了從該DataSource獲取的數(shù)據(jù)庫連接與 Spring 定義的事務(wù)能夠完美地結(jié)合,從而實現(xiàn)業(yè)務(wù)系統(tǒng)與引擎系統(tǒng)事務(wù)的集成。
Activiti5通過BpmnParse使用SAX方式進行BPMN2.0 XML流程定義文件的解析,是解析的核心類,從根節(jié)點開始解析,依次對DefinitionsAttributes、Imports、ItemDefinitions、Messages、Interfaces、和Errors以及ProcessDefinitions各個元素進行解析(以上均是標(biāo)準(zhǔn)的BPMN2.0元素),最后解析負責(zé)流程可視化定義的DiagramInterchangeElements元素。每解析一個元素都會判斷元素類型,如果是“活動“類型(包括Task、Gateway等),則會為活動設(shè)置相應(yīng)的ActivityBehavior,同時如果流程定義文件中定義了額外屬性,Activiti5會自行利用反射機制注入到ActivityBehavior。
除了Command和ActivityBehavior外,Activiti5還大量引入了監(jiān)聽機制(攔截器的概念),目前引擎主要包含四類監(jiān)聽:
PVM流程虛擬機中包含三類事件:Start、End、Take,分別表示流程的啟動、流轉(zhuǎn)和結(jié)束,流程啟動后,流引擎會從Start事件開始執(zhí)行,通過Take事件,驅(qū)動流程流向下一個環(huán)節(jié),該“流向”的動作會被PVM運行時的AtomicOperationTransitionNotifyListenerTake監(jiān)聽,該監(jiān)聽會將附加到該流向的所有執(zhí)行監(jiān)聽依次執(zhí)行。任務(wù)有也有三類事件可以被監(jiān)聽:Create、Assignment、Complete,如果希望在任務(wù)被創(chuàng)建或指定了相關(guān)責(zé)任人或任務(wù)完成后增加些額外的輔助功能,可以創(chuàng)建TaskListener接口的實現(xiàn)類,并將其定義到
Activiti5提供的Command、ActivityBehavior、Listener等接口為引擎的功能擴展提供了方便,如果業(yè)務(wù)系統(tǒng)的功能不能滿足時可以實現(xiàn)這些接口,以無侵入的方式擴展Activiti5,利用這些擴展接口,可以在其執(zhí)行方法中完成很多業(yè)務(wù)邏輯,如權(quán)限校驗、與業(yè)務(wù)系統(tǒng)的交互、與外部系統(tǒng)集成調(diào)用,甚至替換原有功能偷梁換柱暗度陳倉。
ProcessEngine是Activiti系統(tǒng)的核心接口,七類基礎(chǔ)服務(wù)接口通過ProcessEngine獲取,均采用鏈?zhǔn)紸PI方式,直觀明了,易于使用:
RepositoryService:
流程資源服務(wù)的接口,主要用于對流程定義的部署、查詢和刪除操。新流程的部署使用createDeployment().addResourceXXX().deploy()方法;已部署流程的查詢使用createDeploymentQuery()附加查詢條件的方式獲取;另外可以使用deleteDeployment和deleteDeploymentCascade方法進行流程的刪除或級聯(lián)刪除。
TaskService:
任務(wù)服務(wù)接口,該接口暴露了管理人機交互任務(wù)的操作,如任務(wù)領(lǐng)?。╟laiming)、任務(wù)完成(completing)和任務(wù)指派(assigning),還包括對任務(wù)的創(chuàng)建、查詢、保存、刪除等。
RuntimeService:
運行時服務(wù)主要用于啟動或查詢流程實例,以及流程變量、當(dāng)前激活狀態(tài)活動的查詢、流程實例的刪除等。流程在運行過程中所產(chǎn)生的東西都可以使用該接口進行相關(guān)處理。
HistoryService:
流程歷史的服務(wù)接口。提供對歷史流程實例、歷史任務(wù)的查詢和刪除操作,從提供的API來看,歷史流程的查詢其提供了finished和unfinished流程的查詢,即是說,HistoryService提供了對已完成和當(dāng)前正在執(zhí)行流程的活動/任務(wù)查詢,這一點似乎與runtimeService提供的查詢有些沖突,但其實是有差別的,運行時的信息僅包含任意時刻活動的實際運行狀態(tài)信息(是從流程運行執(zhí)行性能上考慮的),而歷史信息是對已經(jīng)固化的信息做簡單查詢而優(yōu)化的,其所持有的對象是不同的。
IdentityService:
用戶、組管理服務(wù)接口,用于管理Group、User的增刪改查,并維護Membership,涉及到的API有newUser、newGroup、saveUser、saveGroup、createMembership以及相關(guān)的deleteXXX方法。
FormService:
表單服務(wù)用于訪問表單數(shù)據(jù)以及在啟動新的流程實例時或完成任務(wù)時所需的渲染后的表單,提供UI界面輔助用戶填寫相關(guān)值以保存至流程變量。該服務(wù)在實際業(yè)務(wù)應(yīng)用中并不常用,屬于引擎的非核心服務(wù)。
ManagementService:
提供流程管理和控制操作的接口服務(wù),和業(yè)務(wù)流程的運行沒有關(guān)聯(lián)關(guān)系,比如查詢數(shù)據(jù)庫本身的內(nèi)容、Activiti的版本及序列生成ID規(guī)則等,屬于引擎的非核心服務(wù)。
Activiti5工作流引擎應(yīng)用需要首先掌握的是配置及API基礎(chǔ)應(yīng)用,下面以上述BPMN2.0請假流程為例,簡述Activiti5在具體系統(tǒng)中的應(yīng)用。
Step1:繪制請假流程圖
請假流程圖使用標(biāo)準(zhǔn)的BPMN2.0圖元進行流程定義,可以使用任何XML編制工具編寫(導(dǎo)入XSD可以為編寫過程提供代碼提示),建議使用Joinwork Process Studio進行可視化編制,如圖3:
圖3:Step2配置Activiti5環(huán)境
流程引擎環(huán)境主要涉及到三個方面:數(shù)據(jù)源、事務(wù)管理以及流程引擎配置實例。通常流程引擎僅是業(yè)務(wù)系統(tǒng)的一個核心模塊,其數(shù)據(jù)源和事務(wù)都要委托給業(yè)務(wù)平臺,在流程引擎配置定義中,可以通過ref將業(yè)務(wù)系統(tǒng)的dataSource和transactionManager注入給Activiti5的引擎配置:
<beanid="processEngineConfiguration"class="org.activiti.spring.SpringProcessEngineConfiguration"><propertyname="dataSource"ref="dataSource" /><propertyname="transactionManager" ref="transactionManager"/><propertyname="databaseSchemaUpdate"value="true"/><propertyname="jobExecutorActivate"value="false"/></bean>
如果是在OSGi環(huán)境中應(yīng)用Activiti5,還需要將業(yè)務(wù)環(huán)境中注冊的dataSource和transactionManager作為OSGi Service引入到當(dāng)前Bundle,然后再進行processEngineConfiguration的配置:
<osgi:referenceid="dataSource"interface="javax.sql.DataSource"/><osgi:referenceid="transactionManager"interface="org.springframework.transaction.PlatformTransactionManager"/>
Step3:部署請假流程定義文件到Activiti5環(huán)境
利用流程引擎提供的RepositoryService接口實現(xiàn)流程的部署:
//通過ProcessEngine獲取repositoryServiceRepositoryServicerepositoryService = processEngine.getRepositoryService();//使用repositoryService進行新流程部署repositoryService.createDeployment().addClasspathResource("請假申請-條件分支與合并流程.bpmn20.xml").deploy();
Step4:創(chuàng)建請假單頁面輸入請假天數(shù)及原由,啟動流程
編寫html表單輸入界面,然后使用Ajax提交請求,由Servlet根據(jù)請求參數(shù)創(chuàng)建新流程實例,啟動流程后界面如圖4:
圖4:流程啟動后的界面
輸入請假天數(shù)及原因,如果天數(shù)大于等于3天,則走“部門經(jīng)理審批路由“分支,利用jQuery綁定”提交“按鈕的操作:
$('#startProcess').click(function(){ varurl = '/com.ygsoft.process.demo/ProcessEngineServlet?operate=start&'+$('#inputform').serialize(); //以UTF8方式提交: $.ajax({ url:url, type:"POST", dataType:"json", contentType:"application/x-www-form-urlencoded;charset=utf-8",//此參數(shù)避免中文亂碼 success:function(data){ if(data.success){ alert('您的單據(jù)已提交,流程ID:'+data.id); $('#inputform').hide(); $('#viewTodo').show(2000); }else{ alert('您的單據(jù)未提交成功'); } } }); })
Backend端利用RuntimeService接口創(chuàng)建新的流程實例:
// 通過ProcessEngine獲取runtimeServiceRuntimeServiceruntimeService = processEngine.getRuntimeService();// 使從Request中獲取請求參數(shù),用于構(gòu)造流程啟動參數(shù)Map<String, Object>params = newHashMap<String, Object>();String processKey = request.getParameter("processKey"); int day = Integer.parseInt(request.getParameter("day"));String reason = request.getParameter("reason");params.put("day", day);params.put("user", user);params.put("reason", reason); // 使用runtimeService啟動流程實例(將參數(shù)做為流程變量處理)ProcessInstanceprocessInstance = runtimeService.startProcessInstanceByKey(processKey,params) ;
Step5:獲取審批人待辦任務(wù)
利用TaskService接口可是實現(xiàn)指配給自己的以及候選任務(wù):// 通過ProcessEngine獲取taskServiceTaskServicetaskService = processEngine.getTaskService();// 使用taskService根據(jù)用戶ID獲取候選任務(wù)List<Task> tasks = taskService.createTaskQuery().taskAssignee(user).orderByTaskCreateTime().desc().list();
將查詢到的List
還有一種情況是查詢分配給某個組或某個人的候選任務(wù):
List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstance.getId()).taskCandidateGroup("xxxGrp").list();// 或List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstance.getId()).taskCandidateUser("xxxUser").list();
Step6:審批人查看任務(wù)明細
任務(wù)明細除了包含Task本身的信息(如任務(wù)名稱、描述以及流程變量等)外,還要動態(tài)顯示當(dāng)前激活任務(wù)的可視化流程圖。
Task信息可以從List
// 根據(jù)當(dāng)前Task獲取流程定義對象 ProcessDefinitionEntityprocessDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService) .getDeployedProcessDefinition(task.getProcessDefinitionId()); // 利用ProcessDiagramGenerator生成當(dāng)前激活任務(wù)的圖片流 InputStreamdefinitionImageStream = ProcessDiagramGenerator.generateDiagram(processDefinition, "png", runtimeService.getActiveActivityIds(task.getProcessInstanceId())); // 將圖片流生成byte[]數(shù)組 byte[] diagramBytes = IoUtil.readInputStream(definitionImageStream,null); response.setContentType("image/png");// 設(shè)置瀏覽器響應(yīng)的ContentType ServletOutputStream out = response.getOutputStream(); out.write(diagramBytes);// 輸出至前端 out.close();
Step7:完成審批任務(wù)
審批人在查看請假申請單后,填寫審批意見后以Ajax方式提交“完成任務(wù)“請求;Servlet利用TaskService進行任務(wù)的提交:
//先完成當(dāng)前任務(wù): Map<String, Object>params = taskService.getVariables(taskId); String reviewMessage = request.getParameter(“msg”); String choice = request.getParameter(“choice”); params.put(“msg”, choice+“-”+user+“-”+reviewMessage); taskService.complete(taskId, params);
待第一個的審批工作完成后,流程引擎會產(chǎn)生Task事件,經(jīng)由并行網(wǎng)關(guān)處理后,系統(tǒng)將生成“人力專員確認“的UserTask任務(wù)和”自動備案“的ServiceTask任務(wù),其中ServiceTask任務(wù)將由系統(tǒng)自動執(zhí)行,”人力專員確認“任務(wù)依然通過Step5、6、7完成,待這兩個任務(wù)都完成后,兩條路由分支由”合并“路由流轉(zhuǎn)到”結(jié)束“節(jié)點,至此,流程結(jié)束。
通過以上API的應(yīng)用分析,Activiti5 API構(gòu)成清晰,針對性更強,不同的功能由相應(yīng)的服務(wù)接口完成,訪問接口更友好。
BPMN2.0是一個工作流業(yè)界標(biāo)準(zhǔn),規(guī)范了大型廠商和開源工作流產(chǎn)品的實現(xiàn),Activiti5實現(xiàn)了該標(biāo)準(zhǔn)的大部分圖元定義和執(zhí)行語義解釋,功能強大,Activiti5可以與IBM、Oracle等大型商用工作流產(chǎn)品流程引擎節(jié)點的核心功能媲美,并且為了簡化應(yīng)用、擴充原有功能,Activiti5又自定義了6個擴展元素和15個擴展屬性,這些元素和屬性能夠與BPMN規(guī)范相互組合可以實現(xiàn)更多、更實用的業(yè)務(wù)功能。
筆者通過技術(shù)組成、對BPMN規(guī)范的覆蓋率、API應(yīng)用友好性、社區(qū)支持度、第三方組件依賴程度以及可擴展性六個方面進行分析和比對,Activiti5的綜合實力較強。對于如何選型符合BPMN標(biāo)準(zhǔn)的工作流產(chǎn)品,這是一個仁者見仁智者見智的問題,一方面依賴于各個公司對工作流技術(shù)方面的歷史積累,另一方面也要針對具體項目具體情況區(qū)別對待。但如果對于一個全新的項目或?qū)BPM3、4設(shè)計理念認同的公司,不妨考慮Activiti5。