spring技術(shù)工作流_第1頁(yè)
spring技術(shù)工作流_第2頁(yè)
spring技術(shù)工作流_第3頁(yè)
spring技術(shù)工作流_第4頁(yè)
spring技術(shù)工作流_第5頁(yè)
已閱讀5頁(yè),還剩9頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、基于Spring創(chuàng)建工作流引擎Spring 框架()是一個(gè)基于 POJO 的輕量級(jí) J2EE 應(yīng)用框架,它支持一種比較新的編程方法:控制反轉(zhuǎn)(Inversion of Contro)。本文介紹 如何把后端處理任務(wù)組織成易于使用、基于Spring的工作流。許多J2EE應(yīng)用程序要求在與主系統(tǒng)分離的上下文中執(zhí)行處理過程。許多情況下,這些 后端過程執(zhí)行幾個(gè)任務(wù),有些任務(wù)依賴于前一個(gè)任務(wù)的狀態(tài)。由于需要處理任務(wù)之間相互依 賴的關(guān)系,使用一套過程式的調(diào)用方法來(lái)實(shí)現(xiàn)通常無(wú)法滿足要求。開發(fā)人員利用Spring, 就很容易把后端過程劃分成一個(gè)個(gè)活動(dòng)組成的集合。Spring容器可以結(jié)合這些活動(dòng),組成 簡(jiǎn)單工作流。

2、本文把簡(jiǎn)單工作流定義為:不需要用戶交互,按預(yù)定順序執(zhí)行的任何一組活動(dòng)。然而, 我們并不建議用這種方法取代現(xiàn)有的工作流框架。如果有些場(chǎng)景需要比較高級(jí)的用戶交互, 譬如基于用戶輸入的分叉、結(jié)合或者轉(zhuǎn)換,使用獨(dú)立的開源或者商用工作流引擎比較有效。 有一個(gè)開源項(xiàng)目已經(jīng)成功地將比較復(fù)雜的工作流設(shè)計(jì)與Spring實(shí)現(xiàn)了集成(參閱: /display/WF/2.3+Spring+什amework)。如果手頭的工作流任務(wù)非常簡(jiǎn)單,那么明智之舉是使用簡(jiǎn)單工作流這一方法,而不是功 能完備的獨(dú)立工作流框架。如果已經(jīng)在使用Spring,更是如此,因?yàn)榭梢员WC迅速實(shí)現(xiàn), 而不會(huì)帶來(lái)項(xiàng)目啟動(dòng)時(shí)間。另外,考慮到Spring

3、輕量級(jí)的控制反轉(zhuǎn)容器具有的特性,Spring 減少了資源開銷。簡(jiǎn)單工作流工作流建模是早在20世紀(jì)70年代就有人研究的一個(gè)課題,許多開發(fā)人員試圖創(chuàng)建標(biāo)準(zhǔn) 化的工作流建模規(guī)范。W.H.M. van der Aalst與人合著的白皮書:工作流模式已成功 地確認(rèn)了一組設(shè)計(jì)模式,這些模式可以準(zhǔn)確地為最常見的的工作流場(chǎng)景建模。其中最基本的 工作流模式是順序(Sequence)模式。順序工作流模式符合簡(jiǎn)單工作流的標(biāo)準(zhǔn),由按順序 執(zhí)行的一組活動(dòng)組成。統(tǒng)一建模語(yǔ)言(UML)活動(dòng)圖通常作為工作流建模的一種機(jī)制使用。圖1顯示了使用標(biāo) 準(zhǔn)的UML活動(dòng)圖來(lái)建模的基本的順序工作流過程。順序工作流是J2EE應(yīng)用程序中很普遍

4、的一種標(biāo)準(zhǔn)工作流模式。J2EE應(yīng)用程序通常需要按順序排列的事件在背景線程中進(jìn)行,或者異步進(jìn)行。圖2的活動(dòng)圖描述了一個(gè)簡(jiǎn)單工作 流,用于通知感興趣的旅客:他們常去的目的地的機(jī)票價(jià)格已下調(diào)。圖1中的航線工作流負(fù)責(zé)創(chuàng)建及發(fā)送動(dòng)態(tài)的電子郵件通知。工作流過程中的每一步就代 表一個(gè)活動(dòng)。工作流啟動(dòng)之前,一些外部事件必須發(fā)生。在這個(gè)例子中,這個(gè)外部事件就是 航線費(fèi)率下調(diào)。我們?cè)敿?xì)看一下航線工作流的業(yè)務(wù)邏輯。如果第一個(gè)活動(dòng)找不到對(duì)費(fèi)率下調(diào)通知有興趣 的用戶,整個(gè)工作流就被取消。如果發(fā)現(xiàn)了有興趣的用戶,就會(huì)完成剩余的幾個(gè)活動(dòng)。隨后, 可擴(kuò)展樣式語(yǔ)言(XSL)轉(zhuǎn)換會(huì)生成消息內(nèi)容,之后記錄審計(jì)信息。最后,試圖通過S

5、MTP 服務(wù)器發(fā)送該消息。如果提交完成又沒有錯(cuò)誤,就記錄成功的信息,結(jié)束整個(gè)過程。但是, 如果在與SMTP服務(wù)器通信時(shí)發(fā)生了錯(cuò)誤,一個(gè)特別的錯(cuò)誤處理例程就會(huì)接管工作。這部 分錯(cuò)誤處理代碼會(huì)試圖重新發(fā)送消息。就這個(gè)航線例子而言,一個(gè)明顯的問題是:如何有效地把順序過程分解成一個(gè)個(gè)活動(dòng)?Spring可以巧妙地處理這個(gè)問題。我們不妨先討論一下Spring這種反轉(zhuǎn)控制框架。Spring把控制對(duì)象的依賴關(guān)系這個(gè)責(zé)任交給了 Spring容器去處理,這樣我們就不必為 之操心。這種責(zé)任的轉(zhuǎn)移就叫控制反轉(zhuǎn)(IoC)或者依賴注射(Dependency Injection)。 Martin Fowler所著的控制反轉(zhuǎn)

6、容器和依賴注射模式( HYPERLINK /articles/injection.html)%e6%af%94%e8%be%83%e6%b7%b1%e5%85%a5%e5%9c%b0%e8%ae%a8%e8%ae%ba%e4%ba%86%e6%8e%a7%e5%88%b6%e5%8f%8d%e8%bd%ac%e5%92%8c%e4%be%9d /articles/injection.html)比較深入地討論了控制反轉(zhuǎn)和依 賴注射。由于Spring可以管理對(duì)象之間的依賴關(guān)系,因而不需要粘合代碼(glue code), 即完全是為了讓類與類能相互協(xié)作而編寫的代碼。作為Spring bean的工作流

7、組件在我們深入討論之前,有必要先來(lái)介紹一下Spring的幾個(gè)主要概念。從BeanFactory 接口繼承而來(lái)的ApplicationContext接口充當(dāng)Spring里面的實(shí)際控制實(shí)體或者容器。ApplicationContext負(fù)責(zé)為一組名為Spring bean的bean創(chuàng)建實(shí)例、進(jìn)行配置及生命 周期管理。只要對(duì)基于XML的配置文件中的Spring bean進(jìn)行裝配,就可以對(duì)ApplicationContext進(jìn)行配置。這個(gè)配置文件規(guī)定了 Spring bean互相協(xié)作的特性。因 而,用Spring的行語(yǔ)來(lái)講,與其他Spring beans交互的Spring bean就叫協(xié)作對(duì)象(coll

8、aborator)。默認(rèn)情況下,Spring bean 在 ApplicationContext 中作為單例(singleton)而存在,但是單例屬性可以設(shè)置成false,實(shí)際上改變了 Spring調(diào)用原型模 式的行為?;氐轿覀兦懊婧骄€費(fèi)率下調(diào)的那個(gè)例子,SMTP發(fā)送例程的抽象被裝配成了工作流過程 例子中的最后一個(gè)活動(dòng)。由于是第5個(gè)活動(dòng),這個(gè)bean被命名為activity5。要發(fā)送消息, activity5就需要委托協(xié)作對(duì)象和錯(cuò)誤處理例程。property name=errorHandlerref bean = mailErrorHandler/property/bean把工作流組件實(shí)施成S

9、pring bean帶來(lái)了兩個(gè)所需的結(jié)果:一是容易進(jìn)行單元測(cè)試;二 是大大提高了重用性??紤]到控制反轉(zhuǎn)容器具有的特性,單元測(cè)試的高效優(yōu)點(diǎn)一目了然。使 用像Spring這樣的控制反轉(zhuǎn)容器,協(xié)作對(duì)象之間的依賴關(guān)系在測(cè)試期間很容易用假的替代 關(guān)系來(lái)置換。在上述例子中,很容易從獨(dú)立的測(cè)試ApplicationContext中檢索到像 activity5這樣的Spring bean。如果用activity5代替假的SMTP委托協(xié)作對(duì)象,就有可 能對(duì)activity5單獨(dú)進(jìn)行單元測(cè)試。第二個(gè)結(jié)果:重用性可通過XSL轉(zhuǎn)換這樣的工作流活動(dòng)來(lái)實(shí)現(xiàn)XSL轉(zhuǎn)換被抽象成工作 流活動(dòng)后,現(xiàn)在就可以由處理XSL轉(zhuǎn)換的任何

10、工作流重復(fù)使用。裝配工作流在提供的API中,Spring控制一小組接口,這些接口的交互方式組成了工作流。關(guān)鍵 接口如下:Activity:封裝了工作流中每一步的業(yè)務(wù)邏輯。ProcessContext:類型ProcessContext的對(duì)象在工作流中的各活動(dòng)之間傳遞。實(shí)現(xiàn) 這個(gè)接口的對(duì)象負(fù)責(zé)在工作流從一個(gè)活動(dòng)轉(zhuǎn)換到另一個(gè)活動(dòng)過程中保持對(duì)象狀態(tài)。ErrorHandler:提供了處理錯(cuò)誤的回調(diào)方法。Processor:描述了為主工作流線程充當(dāng)執(zhí)行者的bean。以下有關(guān)Spring bean配置的代碼利用航線費(fèi)率例子描述了簡(jiǎn)單工作流的過程。bean id = rateDropProcessor cla

11、ss=org.iocworkflow.SequenceProcessorproperty name=activitieslistref bean=activity1/ref bean=activity2/ref bean=activity3/ref bean=activity4/ref bean=activity5/list/propertyproperty name=defaultErrorHandlerref bean=defaultErrorHandler/propertyproperty name=processContextClassvalueorg.iocworkflow.test

12、.sequence.ratedrop.RateDropContext/propertySequenceProcessor類是為順序模式建模的一個(gè)具體子類。有5個(gè)活動(dòng)被連接到了工作流處理器(processor),它會(huì)按順序執(zhí)行這5個(gè)活動(dòng)。與大多數(shù)過程性后端過程相比,工作流解決方案確實(shí)與眾不同,它能夠非??煽康靥幚?錯(cuò)誤??梢詾槊總€(gè)活動(dòng)單獨(dú)裝配錯(cuò)誤處理例程。這種類型的例程在單個(gè)活動(dòng)層面提供了粒度 很細(xì)的錯(cuò)誤處理機(jī)制。如果沒有為某個(gè)活動(dòng)裝配任何錯(cuò)誤處理例程,那么為整個(gè)工作流處理 器定義的錯(cuò)誤處理例程就會(huì)處理問題。就這個(gè)例子而言,如果在工作流過程期間的任何時(shí)刻 出現(xiàn)了未得到處理的錯(cuò)誤,它就會(huì)向外傳播,

13、讓使用defaultErrorHandler屬性裝配而成 的 ErrorHandler bean 來(lái)處理。比較復(fù)雜的工作流框架為數(shù)據(jù)存儲(chǔ)區(qū)在工作流轉(zhuǎn)換期間賦予了持久性的狀態(tài)。在本文中, 我們只關(guān)注狀態(tài)轉(zhuǎn)換自動(dòng)進(jìn)行的簡(jiǎn)單工作流。只有在實(shí)際工作流運(yùn)行期間才能從 ProcessContext處得到狀態(tài)信息。可以看到,ProcessContext接口只有兩個(gè)方法:public interface ProcessContext extends Serializable public boolean stopProcess();public void setSeedData(Object seedObje

14、ct);航線例子工作流所用的具體的ProcessContext類是RateDropContext類。 RateDropContext類封裝執(zhí)行航線費(fèi)率下調(diào)工作流所必需的數(shù)據(jù)。到現(xiàn)在為止,根據(jù)默認(rèn)ApplicationContext的行為,所有bean實(shí)例都已經(jīng)成了單例。 但是對(duì)于航線工作流的每次調(diào)用,我們都要?jiǎng)?chuàng)建RateDropContext類的新實(shí)例。為了滿 足這種需求,需要配置SequenceProcessor,采用完全符合標(biāo)準(zhǔn)的類名作為 processContextClass屬性。對(duì)于每次工作流執(zhí)行,SequenceProcessor都使用指定的 類名,從Spring檢索到Process

15、orContext類的新實(shí)例。這種機(jī)制要起到作用,非單例的 Spring bean 或者類型 org.iocworkflow.test.sequence.simple.SimpleContext 的原 型就必須位于ApplicationContext里面。為工作流播種我們已經(jīng)知道了如何使用Spring組建簡(jiǎn)單工作流,現(xiàn)在著重介紹使用種子數(shù)據(jù)(seed data)來(lái)創(chuàng)建實(shí)例。想知道如何為工作流播種,不妨看一下實(shí)際的接口 Processor所采用 的方法:public interface Processor public boolean supports(Activity activity);pu

16、blic void doActivities();public void doActivities(Object seedData);public void setActivities(List activities);public void setDefaultErrorHandler(ErrorHandler defaultErrorHandler);大多數(shù)情況下,工作流過程需要一些初始的刺激才能啟動(dòng)。啟動(dòng)處理器有兩個(gè)方法: doActivities(ObjectseedData)方法,或者沒有變量的doActivities()。以下代碼片段是包含在示例代碼中為SequenceProces

17、sor實(shí)現(xiàn)的doActivities():public void doActivities(Object seedData) /由Spring注入檢索List activities = getActivities();檢索工作流ProcessContext的新實(shí)例ProcessContext context = createContext();if (seedData != null)context.setSeedData(seedData);按順序執(zhí)行每個(gè)活動(dòng)for (Iterator it = activities.iterator(); it.hasNext();) Activity a

18、ctivity = (Activity) it.next();try context = activity.execute(context); catch (Throwable th) 在活動(dòng)層面確定有沒有錯(cuò)誤處理例程ErrorHandler errorHandler = activity.getErrorHandler();if (errorHandler = null) getDefaultErrorHandler().handleError(context, th);break; else 使用默認(rèn)處理例程處理錯(cuò)誤errorHandler.handleError(context, th)

19、;確保過程可以繼續(xù)執(zhí)行if (processShouldStop(context, activity)break;在這個(gè)航線費(fèi)率下調(diào)的例子中,工作流過程的種子數(shù)據(jù)包括:航線信息和費(fèi)率下調(diào)信息。 利用容易測(cè)試的航線工作流例子,就很容易通過doActivities(Object seedData)方法 為單一工作流過程提供種子數(shù)據(jù),并啟動(dòng)它:BaseProcessor processor =(BaseProcessor)context.getBean(rateDropProcessor);processor.doActivities(createSeedData();rateDropProcess

20、or bean 是從 ApplicationContext 檢索而來(lái)的。 rateDropProcessor其實(shí)裝配成SequenceProcessor的實(shí)例,以處理順序執(zhí)行。createSeedData ()方法為負(fù)責(zé)封裝初始化航線工作流所需的所有種子數(shù)據(jù)的對(duì)象創(chuàng)建了 實(shí)例。處理器選項(xiàng)雖然SequenceProcessor是包括在源代碼里面的Processor的惟一具體子類,但Processor接口的許多實(shí)現(xiàn)是可以想象得到的??梢蚤_發(fā)工作流處理器的其他子類,以控 制不同類型的工作流,譬如說,有著不同執(zhí)行路徑如并行分叉(Parallel Splits)模式的其 他工作流。SequencePro

21、cessor之所以非常適用于簡(jiǎn)單工作流,就是因?yàn)榛顒?dòng)順序已事先 確定。雖然本文并沒有介紹,但排他選擇(Exclusive Choice)模式是適用于使用Spring 的簡(jiǎn)單工作流來(lái)實(shí)現(xiàn)的另一種模式。就排他選擇模式而言,每個(gè)活動(dòng)執(zhí)行完畢后,Processor 具體類會(huì)詢問ProcessorContext:接下來(lái)要執(zhí)行哪一個(gè)Activity。注意:想進(jìn)一步了解并行分叉、排他選擇及其他工作流模式,請(qǐng)參閱W.M.P. van der Aalst等人所著的工作流模式一書。啟動(dòng)工作流考慮到工作流過程常常需要異步執(zhí)行的特點(diǎn),有必要使用分離的執(zhí)行線程來(lái)啟動(dòng)工作流。 有幾種方法能夠以異步方式啟動(dòng)工作流。我們主要

22、介紹兩種:主動(dòng)輪詢隊(duì)列來(lái)啟動(dòng)工作流, 或者通過企業(yè)服務(wù)總線(ESB)如開源ESB: Mule的事件驅(qū)動(dòng)啟動(dòng)方法。圖3和圖4描繪了這兩種啟動(dòng)策略。圖3中,主動(dòng)輪詢出現(xiàn)在這種情況下:工作流中的 第一個(gè)活動(dòng)不斷檢查資源,譬如數(shù)據(jù)源或者POP3電子郵件賬戶。如果圖3中的輪詢活動(dòng) 發(fā)現(xiàn)有任務(wù)等待處理,就開始啟動(dòng)工作流。另一方面,圖4表示了使用Java消息服務(wù)(JMS)的J2EE應(yīng)用程序把事件放到隊(duì)列中的情形。通過ESB配置的事件偵聽器收到圖4中的事件后,為工作流播種,從而啟動(dòng)工 作流過程。主動(dòng)輪詢是啟動(dòng)工作流過程的一種比較簡(jiǎn)單的解決方案。SequenceProcessor極其靈 活,可以讓輪詢啟動(dòng)順暢進(jìn)

23、行。盡管不是令人滿意,但在沒有時(shí)間配置及部署事件驅(qū)動(dòng)型子 系統(tǒng)的許多情況下,主動(dòng)輪詢顯然是合理的選擇。使用Spring的ScheduledTimerTask,就很容易實(shí)現(xiàn)輪詢方案。一個(gè)不足就是,必須 創(chuàng)建額外的Activity才能進(jìn)行輪詢。創(chuàng)建這個(gè)負(fù)責(zé)輪詢的Activity是為了查詢某個(gè)實(shí)體, 譬如數(shù)據(jù)庫(kù)表、pop郵件賬戶或者Web服務(wù),然后確定某個(gè)新的工作是否等待處理。在本文提供的例子中,PollingTest-Case類為基于輪詢的工作流處理器創(chuàng)建實(shí)例。主動(dòng) 輪詢啟動(dòng)不同于事件驅(qū)動(dòng)啟動(dòng)的地方在于,Spring偏愛使用沒有變量的doActivities() 方法。反過來(lái),在事件驅(qū)動(dòng)啟動(dòng)中,啟

24、動(dòng)處理器的實(shí)體通過doActivities(Object seedData)方法提供了種子數(shù)據(jù)。主動(dòng)輪詢的另一個(gè)缺點(diǎn)是:資源被不必要地重復(fù)耗用。 這種資源耗用可能讓人無(wú)法接受,具體耗用多少取決于應(yīng)用程序環(huán)境。以下代碼例子演示了使用主動(dòng)輪詢來(lái)控制工作流啟動(dòng)的一個(gè)活動(dòng):public class PollForWork implements Activitypublic ProcessContext execute(ProcessContext context) throws Exception 先檢查是否有工作需要處理boolean workIsReady = lookIntoDatabaseForWork();if (workIsReady) 輪詢行動(dòng)還必須加載任何種子數(shù)據(jù)(MyContext) context).setSeedData(createSeedData(); else 沒有工作要處理,終止工作流過程(MyContext) context).setStopE

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論