摘要:JBoss Seam是一個(gè)強(qiáng)大的用來(lái)構(gòu)建下一代Web 2.0的應(yīng)用程序框架。JBoss Seam以EJB3.0為核心,擴(kuò)展POJO加注釋的設(shè)計(jì)模式到整個(gè)Web應(yīng)用中。該文主要介紹 JBoss Seam的框架特點(diǎn)和工作原理,并通過一個(gè)簡(jiǎn)單的實(shí)例說(shuō)明了Seam的基本用法,使讀者對(duì)Seam框架有了一個(gè)清楚的了解。
關(guān)鍵詞:Seam;EJB3.0;JSF;POJOs;注釋
中圖法分類號(hào):TP393.09 文獻(xiàn)標(biāo)識(shí)碼:A文章編號(hào):1009-3044(2012)30-7236-04
Java EE5的核心框架定義了三個(gè)層次的標(biāo)準(zhǔn)實(shí)現(xiàn):表示層采用JSF(Java Server Faces),業(yè)務(wù)層和持久層分別采用EJB3.0的Session Bean和Entity Bean。EJB3.0是基于POJO(Plain Old Java Objects)的業(yè)務(wù)服務(wù)和數(shù)據(jù)庫(kù)持久化輕型框架,JSF是基于MVC的Web應(yīng)用框架,兩者雖然功能互補(bǔ),但設(shè)計(jì)理念相對(duì)獨(dú)立,很難在Java EE5框架中進(jìn)行整合。本文將介紹JBoss 針對(duì)Java EE5標(biāo)準(zhǔn)所實(shí)現(xiàn)的應(yīng)用開發(fā)框架——JBoss Seam。正如它取其“縫合”的意義,Seam采用注解方式整合了EJB 3.0和JSF這兩個(gè)Java EE5核心標(biāo)準(zhǔn)。
1 Seam框架分析
1.1 Seam的框架特點(diǎn)
Seam是一個(gè)集JSF、EJB3.0、AJAX和jBPM于一體的全新應(yīng)用框架,下面介紹Seam的主要特點(diǎn)。
1) 基于EJB3.0的開發(fā)
EJB3.0擯棄了傳統(tǒng)EJB粗粒度和重量級(jí)的性質(zhì),轉(zhuǎn)變?yōu)閾碛屑?xì)粒度注釋的輕量級(jí)POJO。因此,Seam框架中表示層組件和業(yè)務(wù)邏輯組件都是EJB。
2) 基于AJAX的遠(yuǎn)程層
Seam提供了內(nèi)置的Javascript遠(yuǎn)程訪問層,允許開發(fā)者通過Ajax異步地從瀏覽器端調(diào)用EJB3.0的Session Bean組件。同時(shí),Seam提供的Ajax解決方案隱藏了XMLHttpRequest API和XML序列化的復(fù)雜性。
3) 富狀態(tài)應(yīng)用程序
傳統(tǒng)的Web應(yīng)用程序中,Http Session是管理Web應(yīng)用狀態(tài)的唯一方法。Seam框架為開發(fā)者提供了多種富狀態(tài)的上下文(Context),支持從會(huì)話狀態(tài)到業(yè)務(wù)過程的多種粒度,讓開發(fā)者在Http Session之外有了更多狀態(tài)管理的選擇。
4) 過程驅(qū)動(dòng)應(yīng)用程序
企業(yè)級(jí)應(yīng)用存在許多業(yè)務(wù)流程和規(guī)則,需要實(shí)現(xiàn)復(fù)雜的工作流和頁(yè)面流,Seam框架通過JBoss jBPM對(duì)業(yè)務(wù)過程管理提供強(qiáng)大支持。
1.2 Seam的工作原理
Seam使用帶注釋的POJOs作為組件進(jìn)行開發(fā),下面從幾個(gè)方面介紹Seam的工作原理。
1) 雙向注入
Seam使用POJO作為服務(wù)組件,并采用依賴注入(DI)聯(lián)結(jié)所有POJO組件。當(dāng)某組件需要使用另一個(gè)組件時(shí),通過注釋(Annotation)向Seam聲明依賴。Seam依據(jù)應(yīng)用當(dāng)前狀態(tài)將這個(gè)依賴組件注入到所需組件中。
同時(shí),Seam擴(kuò)展了依賴注入的概念,允許進(jìn)行雙向注入(bijection)。一方面,組件可以作為一個(gè)變量被注入。另一方面,組件被Session Bean“拋還”給Seam,返回到JSF中。組件利用@In或者@Out注釋可以在JSF頁(yè)面和業(yè)務(wù)邏輯之間雙向地傳遞數(shù)據(jù)。
2) 攔截器
Seam引入攔截器與注釋組合,為POJO對(duì)象提供功能支持。Seam構(gòu)建攔截器的方式是采用標(biāo)準(zhǔn)的Java EE體系。攔截器類中定義攔截方法時(shí),需要使用@AroundInvoke和@InvocationContext注釋。@AroundInvoke注釋用于指定具體的檢查方法,檢查操作完成后,利用ic.proceed()返回到被攔截檢查的業(yè)務(wù)方法。攔截器類通過配置文件和框架代碼進(jìn)行自動(dòng)調(diào)用,實(shí)現(xiàn)執(zhí)行Session Bean中的業(yè)務(wù)邏輯時(shí)進(jìn)行攔截檢查。
3) Seam的多粒度上下文
Seam在傳統(tǒng)上下文的基礎(chǔ)上,添加了多種不同粒度的上下文,并自動(dòng)管理上下文和組件狀態(tài)。下面重點(diǎn)介紹Seam中兩個(gè)重要的上下文。
會(huì)話 (Conversation): 一個(gè)會(huì)話通常包含了許多相關(guān)或串行的用戶請(qǐng)求。比如,一次交談往往需要用戶完成多次請(qǐng)求并響應(yīng)的周期。典型的案例是向?qū)綄?duì)話框,或者電子商務(wù)中的購(gòu)物車。 Seam使用會(huì)話上下文管理這些交談,解決了頁(yè)面回退、刷新、重復(fù)提交、多窗口瀏覽等帶來(lái)的問題。
業(yè)務(wù)流程(Business Process): Seam 還內(nèi)置了在應(yīng)用程序中集成業(yè)務(wù)流程管理的功能。一個(gè)業(yè)務(wù)流程要求工作流完成兩個(gè)操作:一是創(chuàng)建一個(gè)事務(wù),二是批準(zhǔn)這個(gè)事務(wù)。 兩個(gè)事務(wù)都需要與應(yīng)用程序進(jìn)行一次或者多次交談才能完成它們的任務(wù)。Seam 可以簡(jiǎn)單明了地定義這些任務(wù)和交談。
4) 基于Seam的三層架構(gòu)
下面介紹Seam如何將攔截器嵌入三層架構(gòu)中。攔截過程對(duì)于用戶基本是透明的。用戶請(qǐng)求的完整生命周期如圖1所示。
①Seam集成MVC
大多數(shù)應(yīng)用框架需要利用其特有的Servlets實(shí)現(xiàn)MVC架構(gòu),Seam與此不同,它通過在請(qǐng)求中加入監(jiān)聽器和生命周期控制各組件,維持原有JSF請(qǐng)求的生命周期。
在web.xml中,Seam加入了監(jiān)聽器: SeamListener。此監(jiān)聽器在整個(gè)生命周期中被最先請(qǐng)求,并為L(zhǎng)ifecycle對(duì)象設(shè)置ServletContext和Session,Lifecyle類直接保存用于在web層管理狀態(tài)的上下文組件。接著SeamPhaseListener對(duì)象被請(qǐng)求,SeamPhaseListener對(duì)象用于與FacesServlet交互。在faces-config.xml中,SeamPhaseListener已經(jīng)被定義為FacesServlet生命周期的一部分,用于進(jìn)一步管理上下文和存儲(chǔ)請(qǐng)求狀態(tài)。此監(jiān)聽器將數(shù)據(jù)從表現(xiàn)層傳入到業(yè)務(wù)邏輯層。
②Seam集成EJB3.0
業(yè)務(wù)邏輯層的集成使用SeamInterceptor包裹調(diào)用EJB的請(qǐng)求,此攔截器包裹所有調(diào)用POJO EJB的請(qǐng)求,在生命周期中,每當(dāng)包裹請(qǐng)求時(shí),就間接訪問了在Application Context中存儲(chǔ)的組件對(duì)象。雖然組件對(duì)象包含了訪問的EJB,但是它不是簡(jiǎn)單的包裹器對(duì)象。組件對(duì)象持有所有域級(jí)別的對(duì)象——從注入域到數(shù)據(jù)模型對(duì)象,再到驗(yàn)證器?;竞w了任何與POJO屬性級(jí)別相關(guān)的Seam注釋。而且,另一個(gè)較大的擴(kuò)展是包含了其他默認(rèn)的攔截器。這些攔截器處理從雙向注入、驗(yàn)證到業(yè)務(wù)管理的所有事情。
2 Seam的應(yīng)用
2.1任務(wù)要求
用戶注冊(cè)程序要求輸入用戶名、真實(shí)名稱和密碼, 將信息存入數(shù)據(jù)庫(kù)。注冊(cè)成功,顯示已注冊(cè)頁(yè)面,否則,顯示失敗頁(yè)面。本例雖不能完全展示Seam的全部特性,但展示了Seam使用帶注釋的POJOs進(jìn)行開發(fā),并集成JSF和EJB3的特性。
2.2程序結(jié)構(gòu)
該程序需要建立:
1) 兩個(gè)頁(yè)面(register.jsp, registered.jsp)。
2) 一個(gè)實(shí)體Bean(User.java):保存用戶數(shù)據(jù)。
3) 一個(gè)無(wú)態(tài)的Session Bean(RegisterAction.java):作為JSF的action listener。程序結(jié)構(gòu)由圖2所示:
圖2 程序結(jié)構(gòu)圖
2.3 代碼實(shí)現(xiàn)
2.4 程序的工作流程
1) 當(dāng)register.jsp中的表單被提交后,JSF請(qǐng)求Seam處理user變量。此時(shí)任何Seam 上下文中不存在與user變量名綁定的值。Seam實(shí)例化user組件并存儲(chǔ)在Seam Session 上下文中,隨后將User Entity Bean的實(shí)例返回給JSF。
2)Hibernate驗(yàn)證器按照User Entity Bean中的約束定義對(duì)表單中的值進(jìn)行驗(yàn)證。如果與約束不符,JSF刷新頁(yè)面。否則,JSF將表單中的數(shù)據(jù)與User Entity Bean中對(duì)應(yīng)屬性進(jìn)行綁定。
3) JSF請(qǐng)求 Seam處理 register變量,Seam在Stateless 上下文中找到無(wú)態(tài)Bean RegisterAction,返回給JSF。JSF喚醒register()行為監(jiān)聽方法。
4) Seam攔截該方法調(diào)用,將Session上下文中的User實(shí)體注入到方法中。
5) register()檢查注冊(cè)用戶名是否已存在,若存在,則返回FacesMessages附帶的錯(cuò)誤信息及null值,刷新頁(yè)面。若無(wú)此用戶名,則重定向到“/registered.jsp”。JSF生成頁(yè)面時(shí)仍請(qǐng)求Seam從Session上下文中返回User實(shí)體。
3 結(jié)束語(yǔ)
JBoss Seam進(jìn)一步簡(jiǎn)化了Java EE5,建立了更加集成化的EJB3和JSF,它的框架設(shè)計(jì)使 Web應(yīng)用具有強(qiáng)壯性和伸縮性。JBoss Seam已成為現(xiàn)今流行的 Web應(yīng)用框架。
參考文獻(xiàn):
[1] JBoss Seam官方文檔[EB/OL].http://labs.jboss.com/portal/jbossseam/.
[2] Michael Juntao Yuan,Thomas Heute.JBoss(R) Seam: Simplicity and Power Beyond Java(TM) EE[M].US:Prentice Hall PTR,2007.
[3] Joseph Faisal Nusairat.Beginning JBoss? Seam:From Novice to Professional[M].US:Apress Inc,2007:131-140.