<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Sealyu

    --- 博客已遷移至: http://www.sealyu.com/blog

      BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      618 隨筆 :: 87 文章 :: 225 評(píng)論 :: 0 Trackbacks

    作者 Michael Yuan譯者 包亮 發(fā)布于 2007年11月2日 上午1時(shí)3分

    本文節(jié)選了Michael Yuan和Thomas Heute所著的即將出版JBoss Seam: Power and Flexibility Beyond Java EE 5.0第一章和第二章,內(nèi)容有所刪減。


    什么是Seam?

    JBoss Seam是“Java EE 5.0的一個(gè)輕量級(jí)的框架”。這是什么意思?難道Java EE(Enterprise Edition) 5.0本身不是一套“框架嗎”?為什么在官方規(guī)范之外,還需要另外一個(gè)框架?好吧,我們就將seam看作是本應(yīng)該被包括在Java EE 5.0中的一個(gè)“遺漏的框架”吧。它在Java EE 5.0框架的上層,為所有的在企業(yè)Web應(yīng)用中的組件提供了一個(gè)統(tǒng)一的、易于理解的編程模型。它同樣使基于狀態(tài)的應(yīng)用和業(yè)務(wù)流程驅(qū)動(dòng)的應(yīng)用的開(kāi)發(fā)易如反 掌。換句話說(shuō),Seam致力于開(kāi)發(fā)者生產(chǎn)力和應(yīng)用擴(kuò)展性。

    1. 整合和強(qiáng)化Java EE框架

    Java EE5.0的核心框架是EJB(Enterprise JavaBeans)3.0和JSF(JavaServer Faces)1.2。EJB 3.0(以下簡(jiǎn)稱EJB3)是基于一個(gè)POJO(Plain Old Java Objects)的業(yè)務(wù)服務(wù)和數(shù)據(jù)庫(kù)持久化的輕型框架。JSF是一個(gè)基于MVC(Model-View-Controller)的Web應(yīng)用框架。大多數(shù) 的Web應(yīng)用都將包含有業(yè)務(wù)邏輯的EJB3組件和Web應(yīng)用前端顯示的JSF組件。EJB3和JSF雖然互補(bǔ),但是他們是根據(jù)各自的理念設(shè)計(jì)的獨(dú)立的框 架。例如,EJB3使用注解(annotation)來(lái)配置服務(wù),而JSF使用的是XML文件。更進(jìn)一步講,EJB3和JSF組件在框架層面上是互不敏感 的。要整合EJB3和JSF,開(kāi)發(fā)者必須手動(dòng)地構(gòu)造facade對(duì)象(如:JSF支持bean),將業(yè)務(wù)組件與Web頁(yè)面和樣板代碼(又稱 plumbing代碼)聯(lián)結(jié)起來(lái),以便能跨框架調(diào)用方法。將這些技術(shù)粘合起來(lái)是Seam的職責(zé)之一。

    Seam打破了EJB3和JSF之間的人工層,它為整合EJB3和JSF提供了一個(gè)一致的,基于注解的途徑。只需要個(gè)別簡(jiǎn)單的注解,Seam中的 EJB3業(yè)務(wù)組件就能直接被用來(lái)支持JSF Web表單或者處理Web UI事件。Seam允許開(kāi)發(fā)者將“同一種東西”——有注解的POJOs——應(yīng)用與所有的應(yīng)用組件。與其他Web框架開(kāi)發(fā)的應(yīng)用相比,Seam應(yīng)用概念簡(jiǎn) 潔,同樣的功能卻需要較少的代碼(在JAVA和XML中)。如果沒(méi)有耐心,或者想要快速預(yù)覽,一個(gè)Seam到底有多簡(jiǎn)單,你可以現(xiàn)看看本文描述的 hello world一例。

    在JSP來(lái)說(shuō)困難的任務(wù),Seam可以輕易的完成。例如,JSF頭疼的一個(gè)問(wèn)題就是過(guò)分依賴HTTP POST。這使得將一個(gè)添加到書(shū)簽中的JSF網(wǎng)頁(yè),通過(guò)HTTP GET訪問(wèn)相當(dāng)困難。但是有了Seam,生成一個(gè)REST網(wǎng)頁(yè)是非常容易的。Seam提供了一系列JSF組件標(biāo)簽和注解,增加了“web友好”和JSF應(yīng) 用的網(wǎng)頁(yè)效率。

    同時(shí),Seam拓展了EJB3到POJO的組件模式, 從web層到業(yè)務(wù)層都有了狀態(tài)上下文。進(jìn)一步說(shuō),Seam整合了一系列主要的其他開(kāi)放源代碼框架,例如jBPM、JBoss Rules(又名Drools)、JBoss Portal、JBoss Microcontainer等等。Seam不僅能將它們“有機(jī)結(jié)合”起來(lái),而且可以像整合JSF和EJB3一樣強(qiáng)化原有的框架。

    Seam位于Java EE 5.0底層,但它的應(yīng)用并不局限與Java EE 5.0服務(wù)器。一個(gè)Seam應(yīng)用可以部署在J2EE 1.4應(yīng)用服務(wù)器和Tomcat服務(wù)器上。這意味著現(xiàn)在能在Seam應(yīng)用中得到產(chǎn)品化支持。

    1 + 1 > 2

    或許有這樣一種誤解,認(rèn)為Seam僅僅是將各種不同框架串起來(lái)的另外一個(gè)集成框架。Seam提供了它自身管理的狀態(tài)上下文,允許框架通過(guò)注解和EL(表達(dá)式語(yǔ)言)表達(dá)式與其他框架進(jìn)行深度整合。整合的程序來(lái)自于Seam開(kāi)發(fā)者對(duì)第三方框架的認(rèn)知。

    2. 一個(gè)為ORM設(shè)計(jì)的Web框架

    對(duì)象關(guān)系映射(ORM)解決方案在當(dāng)今企業(yè)應(yīng)用中廣為使用。但是,大多數(shù)當(dāng)前的業(yè)務(wù)和web框架并不是為ORM設(shè)計(jì)的,它們并不在整個(gè)Web交互生命周期——從請(qǐng)求來(lái)臨到響應(yīng)完成——管理持久上下文。這就導(dǎo)致了包括可怕的LazyInitializationException在內(nèi)的各種ORM異常,帶來(lái)了如“數(shù)據(jù)傳輸對(duì)象(DTO)”等丑陋的伎倆(ugly hacks)。

    Gavin King發(fā)明了Seam,同時(shí)他也發(fā)明了在世界上廣為使用的ORM解決方案Hibernate。為了繼承和發(fā)揚(yáng)ORM的最佳實(shí)踐,Seam進(jìn)行了重新設(shè) 計(jì)。有了Seam,就不必再寫(xiě)DTO,你所做的就是延遲加載。因?yàn)閿U(kuò)展后的持久上下文就如同一個(gè)自然的高速緩存,可以減少和數(shù)據(jù)庫(kù)的交互,ORM的性能就 會(huì)被極大地改進(jìn)。

    進(jìn)一步講,因?yàn)镾eam整合了ORM層、業(yè)務(wù)層和表示層,開(kāi)發(fā)者就能夠在表示層直接展示ORM對(duì)象,也能把數(shù)據(jù)庫(kù)驗(yàn)證注解用于輸入表單,以及重新定向ORM例外到定制的錯(cuò)誤頁(yè)面。

    3.專為有狀態(tài)Web應(yīng)用而設(shè)計(jì)

    Seam是專為有狀態(tài)Web應(yīng)用而設(shè)計(jì)的。Web應(yīng)用是天生的多用戶應(yīng)用,電子商務(wù)應(yīng)用天生也是有狀態(tài)的和有事務(wù)的。但是,大多數(shù)已有Web應(yīng)用框 架是面向無(wú)狀態(tài)應(yīng)用的。開(kāi)發(fā)者必須操作HTTP會(huì)話(session)對(duì)象來(lái)管理用戶狀態(tài),與核心業(yè)務(wù)邏輯無(wú)關(guān)的代碼不僅會(huì)混亂你的應(yīng)用,而且?guī)?lái)了一系 列的性能問(wèn)題。

    在Seam中,所有的基礎(chǔ)應(yīng)用組件天生地有狀態(tài)。它們使用起來(lái)要比HTTP session容易,因?yàn)樗鼈兊臓顟B(tài)由Seam公開(kāi)管理。沒(méi)有必要在Seam應(yīng)用中編寫(xiě)引起麻煩的狀態(tài)管理代碼——只需在其組件上注解其做用域、生命周期 方法以及其他狀態(tài)屬性,Seam就會(huì)掌管其他[譯者注:指這些組件的生命周期]。Seam狀態(tài)組件要比HTTP會(huì)話(session)能更好的管理用戶狀 態(tài)。例如,你能有多個(gè)“會(huì)話”進(jìn)行,每個(gè)“會(huì)話”由在一個(gè)HTTP會(huì)話(session)中一系列的Web請(qǐng)求和業(yè)務(wù)方法調(diào)用組成。

    進(jìn)一步說(shuō),在Seam中,數(shù)據(jù)庫(kù)緩存和事務(wù)能自動(dòng)與應(yīng)用的狀態(tài)相連。Seam在內(nèi)存中自動(dòng)保存數(shù)據(jù)庫(kù)更新,等到對(duì)話結(jié)束后提交到數(shù)據(jù)庫(kù)。內(nèi)存中的緩存能大大減輕復(fù)雜狀態(tài)應(yīng)用中數(shù)據(jù)庫(kù)的負(fù)載。

    除了以上這些,Seam支持整合開(kāi)源JBoss jBPM業(yè)務(wù)程序引擎,大大提升了Web應(yīng)用中的狀態(tài)管理。你現(xiàn)在能為一個(gè)機(jī)構(gòu)中不同工作人員(諸如客戶、經(jīng)理、技術(shù)支持人員等等)的指定工作流程,利用工作流程來(lái)驅(qū)動(dòng)應(yīng)用,而不是依賴用戶界面事件處理和數(shù)據(jù)庫(kù)。

    4. 支持Web 2.0

    Seam為Web2.0應(yīng)用進(jìn)行了充分的優(yōu)化。它給AJAX(異步JavaScript和XML,增加網(wǎng)頁(yè)交互的一種技術(shù))提供了多種支持——從內(nèi) 置“零Javascript”的AJAX組件到有AJAX支持的JSF組件,再到定制的JavaScript庫(kù),Seam為瀏覽器端的 Javascript對(duì)象提供了直接訪問(wèn)Seam服務(wù)器組件的途徑。Seam提供了一個(gè)先進(jìn)的并發(fā)模型,有效的管理來(lái)自同一用戶的多個(gè)AJAX請(qǐng)求。

    對(duì)于AJAX應(yīng)用,不斷增長(zhǎng)的數(shù)據(jù)庫(kù)負(fù)載是一個(gè)巨大的挑戰(zhàn)。與一個(gè)非AJAX應(yīng)用相比,一個(gè)AJAX應(yīng)用要向服務(wù)器發(fā)送的更頻繁的請(qǐng)求。一但數(shù)據(jù)庫(kù) 必須響應(yīng)這些AJAX請(qǐng)求,那么數(shù)據(jù)庫(kù)就不堪重荷。Seam中的狀態(tài)持久上下文正如一個(gè)內(nèi)存中的緩存,它能在會(huì)話始末保存信息,最終幫助減少數(shù)據(jù)庫(kù)交互。

    Web2.0應(yīng)用往往為其數(shù)據(jù)使用復(fù)雜關(guān)系模型(例如,一個(gè)網(wǎng)絡(luò)交際站點(diǎn)所做的就是處理和顯示“用戶”之間的關(guān)系),對(duì)于這些站點(diǎn),延遲加載對(duì)于 ORM層至關(guān)重要。否則,一個(gè)簡(jiǎn)單的查詢就能級(jí)聯(lián)地加載整個(gè)數(shù)據(jù)庫(kù)。正如我們前面所討論過(guò)的,Seam是現(xiàn)今唯一一個(gè)正確支持Web應(yīng)用延時(shí)加載的Web 框架。

    5.依賴雙向映射的Pojo服務(wù)

    Seam是一個(gè)“輕量級(jí)”框架,因?yàn)樗褂肞OJO(plain old Java objects)作為服務(wù)組件。在應(yīng)用中,POJO沒(méi)有使用接口或抽象類來(lái)"鉤住"組件。當(dāng)然,問(wèn)題是如何使POJO交互來(lái)組成這個(gè)應(yīng)用?它們?nèi)绾闻c容器 服務(wù)(例如,數(shù)據(jù)庫(kù)持久化服務(wù))交互?

    Seam通過(guò)使用一個(gè)流行的、被稱作依賴注入(DI)的設(shè)計(jì)模式聯(lián)結(jié)所有POJO組件。在這個(gè)模式下,Seam框架管理著所有組件的生命周期。當(dāng)一 個(gè)組件需要使用另外一個(gè)時(shí),它通過(guò)注解(annotation)向Seam聲明此依賴。Seam依據(jù)應(yīng)用當(dāng)前狀態(tài)得到這個(gè)依賴組件,并將它注入到所需求的 組件中。

    通過(guò)拓展依賴注入概念,一個(gè)Seam組件A不但可以構(gòu)造另外一個(gè)組件B,而且把此組件B“拋還”給Seam以備其他組件(例如組件C)以后使用。

    這類雙向依賴管理甚至都廣泛的應(yīng)用于簡(jiǎn)單的Seam web應(yīng)用中(例如第二章的hello world一例)。在Seam術(shù)語(yǔ)中,我們稱這個(gè)為“依賴雙向映射”。

    6.非常規(guī)的配置

    [譯者注:指以隱式映射為主題,以顯式映射為例外的配置方式]

    使Seam易用的主要設(shè)計(jì)原則是“非常規(guī)的配置”。其思想是為這些組件提供一系列默認(rèn)行為,開(kāi)發(fā)者只需要在預(yù)期行為非默認(rèn)的時(shí)候,顯示地配置組件。 例如, 當(dāng)Seam將組件A作為屬性注入到組件B時(shí),默認(rèn)地,組件A剛會(huì)以組件B被注入的屬性的名稱命名。Seam里還有很類似的細(xì)節(jié)。總的結(jié)果是Seam中配置 元數(shù)據(jù)要比其他Java框架簡(jiǎn)單的多。因此,大多數(shù)的Seam應(yīng)用能通過(guò)一系列簡(jiǎn)單的Java注解進(jìn)行充分配置。開(kāi)發(fā)者從減化的復(fù)雜度中受益匪淺,最后, 與其他Java框架相比,用更少的代碼實(shí)現(xiàn)同樣的功能。

    7.避免濫用XML

    或許你已經(jīng)注意到,Java注解在表述和處理Seam配置元數(shù)據(jù)時(shí)扮演著重要的角色。通過(guò)這樣的設(shè)計(jì)使框架更易于操作。

    在J2EE發(fā)展早期,XML曾經(jīng)被看作配置管理的“圣杯”。框架設(shè)計(jì)者將所有的配置信息,包括Java類和方法名稱都統(tǒng)統(tǒng)丟進(jìn)XML文檔,而不考慮 對(duì)開(kāi)發(fā)者所帶來(lái)的后果。反省后,發(fā)現(xiàn)這是個(gè)嚴(yán)重的錯(cuò)誤。XML配置文檔太過(guò)重復(fù)。開(kāi)發(fā)者必須重復(fù)代碼中已有的信息,從而將配置和代碼聯(lián)結(jié)起來(lái)。這些重復(fù)使 應(yīng)用易于出錯(cuò)(例如,一個(gè)拼寫(xiě)錯(cuò)誤的類名可能在運(yùn)行時(shí)顯示為一個(gè)難于調(diào)試錯(cuò)誤)。缺少合理的默認(rèn)配置進(jìn)一步使這一問(wèn)題復(fù)雜化。事實(shí)上,在一些框架中,相當(dāng) 數(shù)量的樣板代碼偽裝為XML,可能相當(dāng)于或者超過(guò)實(shí)際應(yīng)用中JAVA代碼的數(shù)量。對(duì)于J2EE開(kāi)發(fā)者,XML的濫用通常被稱為“XML地獄”。

    Java社區(qū)認(rèn)識(shí)到了XML的濫用問(wèn)題,并且已經(jīng)非常成功地用Java代碼中的注解取代了XML。EJB3是Java官方標(biāo)準(zhǔn)化機(jī)構(gòu)促進(jìn)Java企 業(yè)組件中注解使用的一項(xiàng)成果。EJB3完全可選擇的使用XML文檔,它向正確方向邁出了積極的一步。Seam加入了EJB3的注解,為整個(gè)web應(yīng)用拓展 了基于注解的編程模型。

    當(dāng)然,XML對(duì)于配置數(shù)據(jù)并非完全不利。Seam設(shè)計(jì)者認(rèn)識(shí)到XML適用于指定頁(yè)面流程或者定義業(yè)務(wù)流程的web應(yīng)用。XML文檔使開(kāi)發(fā)者集中地管 理整個(gè)web應(yīng)用的工作流程成為可能,同時(shí)也反對(duì)將配置信息分散于java源文件中。工作流程很少能與源代碼耦合,因此XML文檔中并不需要重復(fù)鍵入已存 在于代碼中的信息。

    8.為測(cè)試而設(shè)計(jì)

    Seam為了易于測(cè)試而重新設(shè)計(jì)。因?yàn)樗械腟eam組件都是注解過(guò)的POJO,它們易于進(jìn)行單元測(cè)試。開(kāi)發(fā)者僅僅通過(guò)利用常規(guī)的Java new關(guān)鍵詞來(lái)構(gòu)造實(shí)例,然后在測(cè)試框架(例如JUnit 或者TestNG)中運(yùn)行任何方法。如果需要測(cè)試多個(gè)Seam組件的交互,開(kāi)發(fā)者則逐個(gè)實(shí)例化這些組件,然后手動(dòng)建立它們的相互關(guān)系(也就是顯示地使用 setter 方法,而不是依靠Seam依賴注入功能)。

    集成測(cè)試整個(gè)Seam應(yīng)用比較復(fù)雜,因?yàn)殚_(kāi)發(fā)者必須在Seam容器中運(yùn)行應(yīng)用。Seam用嵌入的輕量級(jí)容器來(lái)幫助該類測(cè)試。在測(cè)試框架中,開(kāi)發(fā)者能按步驟地加載Seam容器,然后運(yùn)行測(cè)試。

    9. 卓越的工具支持

    對(duì)于一個(gè)聚焦于開(kāi)發(fā)者生產(chǎn)力的應(yīng)用框架,開(kāi)發(fā)工具的支持至關(guān)重要。Seam發(fā)布了一個(gè)基于命令行的生成器,稱作 SeamGen。SeamGen類似于Ruby-On-Rails中的生成器,它支持諸如從一個(gè)數(shù)據(jù)庫(kù)生成完整CRUD應(yīng)用的功能,聰明的開(kāi)發(fā)者會(huì)通過(guò)諸 如“編輯/保存/在瀏覽器重新載入”的步驟、有測(cè)試支持的特性,來(lái)改進(jìn)web應(yīng)用。

    但更重要的是,SeamGen生成項(xiàng)目不依賴于主流的Java集成開(kāi)發(fā)環(huán)境,如Eclipse和NetBeans。有了SeamGen,開(kāi)發(fā)者可以隨時(shí)入門(mén)。

    10. 讓我們開(kāi)始編碼吧

    總而言之,Seam為JavaEE應(yīng)用削減了開(kāi)發(fā)費(fèi)用,同時(shí),增加了Java EE 5.0不具有的強(qiáng)大的新功能。在下節(jié)(節(jié)選自本書(shū)第二章),我們將給您展示一些實(shí)際代碼例子來(lái)闡述Seam如何工作的。你能通過(guò)網(wǎng)站http://www.michaelyuan.com/seam/下載到本書(shū)中所有的例子的源代碼。

    Seam Hello World

    JBoss Seam是EJB3和JSF中間的粘合劑,這是Jboss Seam最基本的和最廣泛的應(yīng)用。通過(guò)被Seam管理的組件,Seam允許這兩個(gè)框架之間無(wú)縫(不是有意雙關(guān)的)的集成。它為整個(gè)web應(yīng)用拓展了基于注 解的EJB3 POJO編程模型。在層與層之間,沒(méi)有了必需的手動(dòng)JNDI查找,沒(méi)有了冗長(zhǎng)的JSF支持bean的聲明,沒(méi)有了過(guò)多facade方法,沒(méi)有了艱辛的對(duì)象 傳遞,快哉!

    繼續(xù)在Seam中使用JavaEE模式

    在傳統(tǒng)的java EE應(yīng)用中,一些設(shè)計(jì)模式,例如JNDI查找、XML聲明組件、值對(duì)象、facade是被強(qiáng)制使用的。Seam用基于注解的POJO消除了這些人為的需求。但是,當(dāng)Seam應(yīng)用中真正需要它們的時(shí)候,仍然可以自由地使用這些模式。

    編寫(xiě)一個(gè)Seam web應(yīng)用概念上很簡(jiǎn)單。你只需要編碼出下列組件:

    • 實(shí)體對(duì)象代表數(shù)據(jù)模型。實(shí)體對(duì)象可能是JPA或者Hibernate中的POJO對(duì)象。它們自動(dòng)地映射到關(guān)系數(shù)據(jù)庫(kù)表。
    • SF web頁(yè)面展示了用戶界面。頁(yè)面通過(guò)表單捕獲用戶的輸入,并且顯示結(jié)果。表單域與其數(shù)據(jù)顯示數(shù)據(jù)庫(kù)表,這些表被映射到實(shí)體bean或者實(shí)體bean的集合上。
    • EJB3 會(huì)話bean或者注解過(guò)的Seam POJO可以作為JSF Web頁(yè)面的UI事件處理器。它們處理封裝在實(shí)體bean中的用戶輸入,為下一步(或者頁(yè)面)生成顯示的數(shù)據(jù)對(duì)象。

    所有以上組件均由Seam自行管理,它們?cè)谶\(yùn)行時(shí)被自動(dòng)注入到正確的頁(yè)面或者對(duì)象。例如,當(dāng)用戶單擊按鈕提交一個(gè)JSF表單,Seam就會(huì)自動(dòng)解析 表單域并構(gòu)造一個(gè)實(shí)體bean。然后,Seam將實(shí)體bean傳入同樣被Seam構(gòu)造的事件處理器會(huì)話bean中來(lái)處理。開(kāi)發(fā)者不需要在代碼中管理組件的 生命周期和組件之間的相互關(guān)系。依賴處理過(guò)程中,沒(méi)有樣板代碼和XML文件。

    本章中,我們使用hello world一例來(lái)明確展示Seam如何粘合一個(gè)web應(yīng)用。該例子工作如下:用戶能在web表單中輸入其名字來(lái)“問(wèn)候”Seam。一旦她提交了表單,應(yīng)用 則保存她的名字到一個(gè)關(guān)系數(shù)據(jù)庫(kù)中,并且顯示所有已經(jīng)“問(wèn)候”過(guò)Seam的用戶。該項(xiàng)目示例在該書(shū)下載的源代碼中的HelloWorld文件夾中。為了建 立它,你必須安裝Apache ANT 1.6版本以上 (http://ant.apache.org/)。進(jìn)入HelloWorld目錄,運(yùn)行命令ant,則會(huì)生成build/jars /helloworld.ear文件,可以直接拷貝該文件到Jboss AS實(shí)例的server/default/deploy目錄下。現(xiàn)在,啟動(dòng)JBoss AS并且打開(kāi)網(wǎng)址http://localhost:8080/helloworld/。

    為了運(yùn)行本書(shū)中的例子,我們建議您使用JEMS GUI安裝程序安裝一個(gè)與Seam兼容的JBoss AS。您可以從http://labs.jboss.com/portal/jemsinstaller/downloads下載JEMS安裝程序。如果您需要更多安裝JBoss AS和應(yīng)用部署幫助,請(qǐng)參見(jiàn)附錄A,“安裝和部署JBoss AS”

    歡迎使用示例作為模板,快速開(kāi)始你自己Seam項(xiàng)目(參見(jiàn)附錄B “使用應(yīng)用示例作為模板”)。或者,你能使用命令行工具Seam Gen (參見(jiàn)第四章“快速應(yīng)用開(kāi)發(fā)工具”)自動(dòng)生成項(xiàng)目模板,包括所有的配置文件。本章中,我將花少量的時(shí)間來(lái)闡釋源代碼項(xiàng)目中的目錄結(jié)構(gòu)。相反,我們將集中討 論代碼和配置,這也是開(kāi)發(fā)者建立一個(gè)Seam 應(yīng)用必需的。如此,我們就能將知識(shí)應(yīng)用到任何一個(gè)項(xiàng)目結(jié)構(gòu),而不需要受模板的限制。

    源代碼目錄

    一個(gè)Seam應(yīng)用由java類和XML或文本配置文件組成。本書(shū)的項(xiàng)目例子中,java源代碼文件在src目錄中,網(wǎng)頁(yè)在view 目錄中,所有的配置文件都在resources目錄中。更多信息請(qǐng)看附件B,使用應(yīng)用示例作為模板。

    1. 創(chuàng)建一個(gè)數(shù)據(jù)模型

    Helloworld應(yīng)用中的數(shù)據(jù)模型僅僅是一個(gè)有name和id屬性的person 類。注解@Entity告訴容器映射該類到一個(gè)關(guān)系數(shù)據(jù)庫(kù)表,每個(gè)屬性對(duì)應(yīng)表中一個(gè)字段,每個(gè)person實(shí)例相當(dāng)于表中的一條記錄。因?yàn)镾eam采用非常規(guī)的配置方式,容器為表名和字段中僅僅使用類名和屬性名。屬性id上的@Id@GeneratedValue注解暗示id字段是主鍵,它的值是應(yīng)用服務(wù)器為每個(gè)保存到數(shù)據(jù)庫(kù)的peron對(duì)象自動(dòng)生成。

    @Entity
    @Name("person")
    public class Person implements Serializable {

    private long id;
    private String name;

    @Id @GeneratedValue
    public long getId() { return id;}
    public void setId(long id) { this.id = id; }

    public String getName() { return name; }
    public void setName(String name) {this.name = name;}
    }

    Person類中最重要的注解是@Name,它為這個(gè)將要注冊(cè)于Seam中的Person bean指定了名稱。在其他Seam組件中(例如,頁(yè)面和會(huì)話bean)中,開(kāi)發(fā)者能指直接使用“person”來(lái)引用被管理的Person bean

    2. 將數(shù)據(jù)模型映射到web表單

    在JSF頁(yè)面中,我們使用Person bean來(lái)支持表單輸入文本域。#{person.name}符號(hào)指代名為“person”的Seam組件的name屬性,名為“person”的Seam組件是Person實(shí)體bean的一個(gè)實(shí)例。

    <h:form>
    Please enter your name:<br/>
    <h:inputText value="#{person.name}" size="15"/><br/>
    <h:commandButton type="submit" value="Say Hello"
    action="#{manager.sayHello}"/>
    </h:form>

    通過(guò)以下的實(shí)體表單,JSF頁(yè)面顯示了數(shù)據(jù)庫(kù)中所有已經(jīng)向Seam說(shuō)“hello”的用戶。用戶名單列表存儲(chǔ)在一個(gè)名為“fans”的Seam組件中,它是一個(gè)List 對(duì)象。JSFdataTable通過(guò)遍歷列表,每一行顯示一個(gè)Person對(duì)象。Fan標(biāo)記是fans列表的迭代子。

    <h:dataTable value="#{fans}" var="fan">
    <h:column>
    <h:outputText value="#{fan.name}"/>
    </h:column>
    </h:dataTable>

    圖2.1顯示了Hello World網(wǎng)頁(yè)

    當(dāng)用戶點(diǎn)擊“Say Hello”按鈕提交表單,Seam用輸入數(shù)據(jù)構(gòu)造了該person組件。然后它調(diào)用了名為“manager”的Seam 組件的sayhello()的方法(像這樣,#{manager.sayHello}是表單提交按鈕的UI事件處理器),這就在數(shù)據(jù)庫(kù)中保存了person對(duì)象并且刷新了fans列表。名為manager的組件是一個(gè)EJB3的會(huì)話bean, 我們將在下節(jié)討論該話題。

    2. 處理web事件

    Seam 中的名為manager的組件是會(huì)話bean ManagerAction,正如該類中@Name注解指定的。ManagerAction類personfans兩個(gè)屬性,這兩個(gè)屬性被@In@Out所注解。

    @Stateless
    @Name("manager")
    public class ManagerAction implements Manager {

    @In @Out
    private Person person;

    @Out
    private List <Person> fans;

    注解@In和@Out在Seam編程模型中處于核心。因此,讓我們看看到底它們?cè)谶@里是做什么的。

    注解@In告訴Seam,在此會(huì)話bean中,執(zhí)行任何一個(gè)方法之前,Seam就會(huì)把由JSF表單構(gòu)造的名為person組件賦給該person字 段(通過(guò)依賴注入)。開(kāi)發(fā)者能為@In中的注入的組件指定一個(gè)任意的名稱,但是如果沒(méi)有指定,如這里所示,Seam會(huì)將同類型以及同名稱的組件注入到該字 段中。注解@Out告訴Seam,在執(zhí)行任何方法后,Seam會(huì)將屬性fans值和屬性person的值都賦給被Seam管理的同名的組件。在Seam 中,我們將這個(gè)操作稱作 “依賴拋出”。以此,在ManagerAction.sayHello()方法中,我們僅僅需要更新屬性fans和屬性person的值,它們會(huì)自動(dòng)顯示 在頁(yè)面上。

    什么是雙向映射

    在Seam 文件中,有時(shí)你就會(huì)看到術(shù)語(yǔ)“雙向映射”。它指的是被Seam管理的組件和Seam管理上下之間的注入和拋出。

    因?yàn)?strong>person屬性已經(jīng)通過(guò)注入持有了表單數(shù)據(jù),sayHello()方法僅僅是通過(guò)JPA EntityManager將它保存到數(shù)據(jù)庫(kù)中,JPA EntityManager也是通過(guò)@PersistenceContext注入的。當(dāng)方法返回之后,它便更新了fansperson對(duì)象并且把這兩個(gè)對(duì)象拋出。方法sayHello()一般會(huì)返回null,預(yù)示著在調(diào)用之后,更新的數(shù)據(jù)模型將在當(dāng)前的JSF頁(yè)面顯示。

      @PersistenceContext
    private EntityManager em;

    public String sayHello () {
    em.persist (person);
    person = new Person ();
    fans = em.createQuery("select p from Person p")
    .getResultList();

    return null;
    }

    除了一些細(xì)節(jié),我們基本完成了。可能你已經(jīng)注意到,ManagerAction bean類實(shí)現(xiàn)了Manager接口。為了符合EJB3會(huì)話bean 規(guī)范,我需要一個(gè)能列出bean中所有業(yè)務(wù)方法的方法。下面是接口Manager代碼,幸運(yùn)的是,用任何高級(jí)IDE工具都能輕松地自動(dòng)生成這個(gè)接口。

    @Local
    public interface Manager {
    public String sayHello ();
    }

    這就是在Hello World例子中需要的所有代碼。后面兩章小節(jié)將涵蓋Seam應(yīng)用的其他方法和配置。如果開(kāi)發(fā)者為了自己的小型數(shù)據(jù)庫(kù)應(yīng)用想立即編碼和定制helloworld項(xiàng)目,那么現(xiàn)在就可以跳過(guò)本章的剩余部分。

    4. 更易于理解的seam編程模型

    現(xiàn)在我們已經(jīng)大致了解了Hello World的應(yīng)用。但是我們還有一些重要的話題繼續(xù),例如其他折中途徑以及前面代碼沒(méi)有涉及到重要特性,我們將在本節(jié)討論這些話題。它們能幫助開(kāi)發(fā)者對(duì)seam更深刻的理解,但是如果你沒(méi)有耐心,可以直接跳過(guò)本節(jié),需要的時(shí)再來(lái)閱讀。

    4.1 Seam POJO組件

    上例中,我們用一個(gè)EJB3會(huì)話bean實(shí)現(xiàn)了應(yīng)用邏輯,但是我們并不局限于EJB3組件。事實(shí)上,Seam中任何一個(gè)有@Name注解的POJO都能被轉(zhuǎn)化為一個(gè)可管理的組件。

    例如,我們能將ManagerAction轉(zhuǎn)化為一個(gè) POJO,而不是一個(gè)EJB3 session bean。

    @Name("manager")
    public class ManagerAction {

    @In (create=true)
    private EntityManager em;

    ... ...
    }

    使用POJO取代EJB3 bean有正反兩方面意見(jiàn),使用POJO編程時(shí)很簡(jiǎn)單,因?yàn)樗鼈儾恍枰狤JB3特有的注解和接口(參見(jiàn)上文)。如果你的所有業(yè)務(wù)組件都是Seam POJO, 那么你就能不依賴EJB3應(yīng)用服務(wù)器,運(yùn)行你的Seam 應(yīng)用(參見(jiàn)23章,沒(méi)有EJB3的Seam)。

    但是,POJO比EJB3的功能少,因?yàn)镻OJO不能獲得EJB3容器服務(wù)。在不依賴EJB3的Seam 中喪失的EJB3服務(wù)就包括以下幾點(diǎn):

    • @PersistenceContext注入在POJO中不在管用。為了在一個(gè)Seam POJO中得到EntityManager,開(kāi)發(fā)者不得不在Seam配種文件中初始化EntityManager,然后使用Seam注解@In將它注入到POJO中。
    • POJOs中將不在支持方法級(jí)別事務(wù)聲明(declarative method-level transaction)。相反,你可以配置Seam來(lái)劃分事務(wù),可以從收到web請(qǐng)求開(kāi)始直到響應(yīng)頁(yè)面產(chǎn)生結(jié)束。
    • Seam POJO不是消息驅(qū)動(dòng)組件。
    • 不支持注解為@Asynchronous的方法。
    • 不支持容器安全管理。
    • 沒(méi)有事務(wù)或者組件級(jí)別的持久上下文。Seam POJO中的所有的持久上下文都是經(jīng)過(guò)拓展的(更多細(xì)節(jié)請(qǐng)參見(jiàn)7.1 “默認(rèn)的對(duì)話作用域”)。
    • 沒(méi)有集成容器管理的體系結(jié)構(gòu)(例如,JMX控制臺(tái)服務(wù))。
    • Seam POJO方法中沒(méi)有Java RMI。
    • Seam POJO不能是注解為@WebService組件。
    • 沒(méi)有JCA集成。

    所以當(dāng)在EJB3容器中進(jìn)行部署時(shí),為什么每個(gè)人都想使用POJO組件?答案就是,POJO組件對(duì)于純“業(yè)務(wù)邏輯”組件非常有益。POJO為其他組 件代理了數(shù)據(jù)訪問(wèn)、消息傳遞和其他基本功能。例如,我們能使用POJO組件操縱Seam數(shù)據(jù)訪問(wèn)對(duì)象,這對(duì)“業(yè)務(wù)邏輯”POJO是非常有用的,因?yàn)樗鼈兛? 以在需要的時(shí)候,在其他框架中被重用。但是總的來(lái)說(shuō),它們的應(yīng)用要比EJB3組件少,特別是在中小型應(yīng)用中。所以,本書(shū)的大多數(shù)例子我們都使用EJB3組 件。

    4.2 易于測(cè)試

    我們已經(jīng)在第一章中提到,Seam為了不依賴容器的方便的測(cè)試,進(jìn)行了重新設(shè)計(jì)。在helloworld項(xiàng)目中,我們?cè)跍y(cè)試文件夾中包括了單元測(cè)試和集成測(cè)試這兩個(gè)測(cè)試用例。在純Java SE環(huán)境下,Seam 測(cè)試體系模擬了數(shù)據(jù)庫(kù)、JSF、Seam上下文以及其他應(yīng)用服務(wù)器服務(wù),只要運(yùn)行ant test命令就能運(yùn)行所有的測(cè)試。

    4.3 基于Getter和Setter的雙向映射

    在Hello World一例中,我們已經(jīng)展示了通過(guò)成員變量對(duì)Seam組件進(jìn)行的雙向映射,你也能通過(guò)Getter和Setter方法對(duì)組件進(jìn)行雙向映射。例如,以下代碼就工作的很好。

    private Person person;
    private List <Person> fans;

    @In
    public void setPerson (Person person) {
    this.person = person;
    }
    @Out
    public Person getPerson () {
    return person;
    }
    @Out
    public List <Person> getFans () {
    return fans;
    }

    雖然以上的getter和setter方法看似輕微,利用getter和setter方法的雙向映射真正的價(jià)值在于能其加入定制邏輯來(lái)操縱雙向映射的過(guò)程。例如,你可以驗(yàn)證被注入的對(duì)象或者快速地從數(shù)據(jù)庫(kù)重新得到被拋出的對(duì)象。

    4.4避免過(guò)度的雙向映射

    在Hello World一例中 ,通過(guò)將數(shù)據(jù)組件作為業(yè)務(wù)組件的屬性,可以輕易的減少或者消除雙向映射。在JSF頁(yè)面中,通過(guò)這種方式,開(kāi)發(fā)者只需要引用業(yè)務(wù)組件,而不需要在業(yè)務(wù)組件和 數(shù)據(jù)組件之間的雙向映射。例如,開(kāi)發(fā)者可以修改 ManagerAction類為以下所述。

    依賴雙向映射是一個(gè)非常實(shí)用的設(shè)計(jì)模式。但是,正如其他設(shè)計(jì)模式,過(guò)度使用就會(huì)有害。過(guò)度的依賴雙向映射讓代碼變得難以閱讀,因?yàn)殚_(kāi)發(fā)者必須理解每個(gè)注入的組件出自何處。過(guò)度的依賴雙向映射也能增加性能消耗,因?yàn)殡p向映射是在運(yùn)行時(shí)進(jìn)行。

    @Stateless
    @Name("manager")
    public class ManagerAction implements Manager {

    private Person person;
    public Person getPerson () {return person;}
    public void setPerson (Person person) {
    this.person = person;
    }

    private List <Person> fans;
    public List<Person> getFans () {return fans;}

    ... ...
    }

    接下來(lái),我們?cè)陧?yè)面上引用的屬性如下:

    <h:form>

    Please enter your name:<br/>

    <h:inputText value="#{manager.person.name}"/>
    <br/>
    <h:commandButton type="submit" value="Say Hello"
    action="#{manager.sayHello}"/>
    </h:form>
    ... ...
    <h:dataTable value="#{manager.fans}" var="fan">
    <h:column>
    <h:outputText value="#{fan.name}"/>
    </h:column>
    </h:dataTable>

    最后,具有了依賴管理的Seam是多用的。通常用數(shù)據(jù)訪問(wèn)業(yè)務(wù)組件封裝數(shù)據(jù)是一項(xiàng)好的實(shí)踐,特別是針對(duì)有狀態(tài)業(yè)務(wù)組件。

    4.5 JSF中的頁(yè)面導(dǎo)航

    本例中,只有一個(gè)頁(yè)面。每次點(diǎn)擊按鈕后,JSF頁(yè)面會(huì)重新顯示更新過(guò)的數(shù)據(jù)模型。顯然,大多數(shù)web應(yīng)用多于一個(gè)頁(yè)面。在JSF中,一個(gè)用戶界面事件處理器能通過(guò)返回導(dǎo)航規(guī)則名稱,決定下一步該顯示哪個(gè)頁(yè)面。例如,開(kāi)發(fā)者可以在navigation.xml中定義以下導(dǎo)航規(guī)則。

    <navigation-case>
    <from-outcome>anotherPage</from-outcome>
    <to-view-id>/anotherPage.jsp</to-view-id>
    </navigation-case>

    之后,如果sayHello()方法返回一個(gè)名為“another page”的字符串,JSF下一步就該展示anotherPage.jsp。UI事件處理器決定了接下來(lái)要顯示哪個(gè)頁(yè)面,從而為我們帶來(lái)了有步驟的控制。

    4.6 通過(guò)EntityManager訪問(wèn)數(shù)據(jù)庫(kù)

    JPA(Java Persistence API)EntityManager管理著關(guān)系數(shù)據(jù)庫(kù)表與實(shí)體bean 之間的映射。EntityManager 在運(yùn)行時(shí)由應(yīng)用服務(wù)器創(chuàng)建。你能使用注解@PersistenceContext,注入一個(gè)EntityManager的實(shí)例。

    EntityManager.persist()方法將實(shí)體bean存為與之對(duì)應(yīng)數(shù)據(jù)表的一條記錄。 EntityManager.query()方法運(yùn)行SQL化的查詢,并以實(shí)體bean集合形式從數(shù)據(jù)庫(kù)返回?cái)?shù)據(jù)。更多細(xì)節(jié)請(qǐng)參考JPA文件中關(guān)于如何使 用EntityManager和查詢語(yǔ)言。在本書(shū)中,我們只用最簡(jiǎn)單的查詢語(yǔ)句。

    默認(rèn)地,EntityManager將數(shù)據(jù)存于嵌入的HSQL數(shù)據(jù)庫(kù)中。如果在本機(jī)上運(yùn)行Jboss AS,可以通過(guò)以下步驟,為HSQL數(shù)據(jù)庫(kù)開(kāi)啟一個(gè)GUI控制臺(tái):訪問(wèn)http://localhost:8080/jmx-console/,點(diǎn)擊database=localDB,service=Hypersonic MBean服務(wù),之后,點(diǎn)擊在startDatabaseManager方法下方的“invoke”按鈕。你就可以從控制臺(tái)執(zhí)行任意SQL指令。

    5. 配置和打包

    下面,我們將轉(zhuǎn)移話題,討論配置文件和應(yīng)用程序打包。實(shí)際上,你可以通過(guò)Seam Gen命令行工具,生成幾乎所有的配置文檔和構(gòu)造腳本文件。或者你也可以簡(jiǎn)單的重用在示例中的源文件。所以,如果你想首先學(xué)習(xí)Seam編程技術(shù),但又擔(dān)心 接下來(lái)的配置和部署,這個(gè)是很正常的。你可以完全放心地跳過(guò)本節(jié),需要的時(shí)候可以再次閱讀。

    本節(jié)中,我們集中探討Seam EJB3組件配置,JBoss AS外的Seam POJO配置和部署當(dāng)然是可行的。

    大多數(shù)Seam配置文件都是XML文檔。但是等等!我們剛才不是承諾Seam能讓我們擺脫J2EE和Spring中的XML地獄嗎?為什么它又有了 XML文檔呢? 是的,XML文檔確實(shí)有很多用處。XML文檔非常適合部署階段的配置(例如web應(yīng)用的根URL和后臺(tái)數(shù)據(jù)庫(kù)的定位)。因?yàn)樗试S我們?cè)诓渴痣A段改變配置 而不需要改變和重新編譯源代碼。它也適合粘合應(yīng)用服務(wù)器中的不同子系統(tǒng)(例如,配置如何讓JSF組件與Seam EJB3組件交互)。XML文檔也非常適合表示層相關(guān)內(nèi)容(例如網(wǎng)頁(yè)和頁(yè)面導(dǎo)航流程)。

    我們反對(duì)在XML文檔中重復(fù)已經(jīng)存在于Java源代碼中的信息。開(kāi)發(fā)者很快就會(huì)發(fā)現(xiàn),這個(gè)簡(jiǎn)單的SeamEJB3 應(yīng)用有多個(gè)XML配置文檔,每個(gè)文檔那個(gè)都非常簡(jiǎn)短,并且沒(méi)有一個(gè)包含存在于Java代碼中的信息。換句話說(shuō),Seam中沒(méi)有“XML代碼”。

    進(jìn)一步講,XML文檔中的大多數(shù)內(nèi)容都是靜態(tài)的。所以開(kāi)發(fā)者能在自己的Seam應(yīng)用中輕松地重用這些文檔。如何使用示例作為自己的應(yīng)用模板的介紹,請(qǐng)參見(jiàn)附錄B——使用應(yīng)用示例作為模板。

    我們將用下面幾頁(yè)來(lái)詳細(xì)講解示例應(yīng)用的配置文檔和打包后的目錄結(jié)構(gòu)。如果你沒(méi)有耐心看下去,而且很滿意這個(gè)應(yīng)用模板,你可以跳過(guò)以下內(nèi)容。不管怎 樣,不再羅嗦, 我們一起來(lái)了解hello world示例是如何進(jìn)行配置和打包的。為了構(gòu)建一個(gè)JBoss AS的部署Seam 應(yīng)用,我們必須將以上所有java 類和配置文檔打包為企業(yè)應(yīng)用程序歸檔(EAR)。該例中,EAR文件是helloworld.ear。它包含了三個(gè)JAR文件那個(gè)和兩個(gè)XML配置文檔。

    helloworld.ear
    |+ app.war //包含Web頁(yè)面等
    |+ app.jar //包含Seam組件
    |+ jboss-seam.jar // Seam庫(kù)
    |+ META-INF
    |+ application.xml
    |+ jboss-app.xml
    源代碼目錄

    在此項(xiàng)目的源代碼中,resources/WEB-INF目錄包含屬于app.war/WEB-INF目錄的配置文檔。resources /META-INF目錄包含屬于app.jar/META-INF和helloworld.ear/META-INF的文檔。Resources根目錄包 含屬于根目錄app.jar的文檔。

    application.xml文檔列出了在EAR中的JAR文件,并為該應(yīng)用指定了根URL。

    <application>
    <display-name>Seam Hello World</display-name>

    <module>
    <web>
    <web-uri>app.war</web-uri>
    <context-root>/helloworld</context-root>
    </web>
    </module>

    <module>
    <ejb>app.jar</ejb>
    </module>

    <module>
    <java>jboss-seam.jar</java>
    </module>

    </application>

    jboss-app.xml文檔為該應(yīng)用指定了類加載器,每個(gè)EAR應(yīng)用的類加載器應(yīng)該有一個(gè)唯一的名稱。這里我們使用應(yīng)用程序名作為類加載器的名稱,以避免重復(fù)。

    <jboss-app>
    <loader-repository>
    helloworld:archive=helloworld.ear
    </loader-repository>
    </jboss-app>

    jboss-seam.jar是Seam發(fā)布Seam類庫(kù)。app.war和app.jar文檔由我們來(lái)建構(gòu)。所以,下面我們要研究app.war和app.jar。

    5.1. WAR文件

    app.war是按照Web應(yīng)用程序歸檔規(guī)范打包的JAR文件,它包含頁(yè)面和標(biāo)準(zhǔn)的JSF/Seam配置文檔。你還可以將JSF特有的類庫(kù)文件放入WEB-INF/lib目錄 (例如jboss-seam-ui.jar)。

    app.war
    |+ hello.jsp
    |+ index.html
    |+ WEB-INF
    |+ web.xml
    |+ faces-config.xml
    |+ components.xml
    |+ navigation.xml

    web.xml文檔是所有java EE web應(yīng)用必需的。JSF用它來(lái)配置JSF servlet控制器,Seam用它來(lái)攔截所有的web請(qǐng)求。該配置文檔的相當(dāng)標(biāo)準(zhǔn)。

    <web-app version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="..."
    xsi:schemaLocation="...">

    <!-- Seam -->
    <listener>
    <listener-class>
    org.jboss.seam.servlet.SeamListener
    </listener-class>
    </listener>

    <!-- MyFaces -->
    <listener>
    <listener-class>
    org.apache.myfaces.webapp.StartupServletContextListener
    </listener-class>
    </listener>

    <context-param>
    <param-name>
    javax.faces.STATE_SAVING_METHOD
    </param-name>
    <param-value>client</param-value>
    </context-param>

    <servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>
    javax.faces.webapp.FacesServlet
    </servlet-class>
    <load-on-startup>1</load-on-startup>
    </servlet>

    <!-- Faces Servlet Mapping -->
    <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.seam</url-pattern>
    </servlet-mapping>
    <context-param>
    <param-name>javax.faces.CONFIG_FILES</param-name>
    <param-value>/WEB-INF/navigation.xml</param-value>
    </context-param>
    </web-app>

    faces-config.xml文檔是JSF標(biāo)準(zhǔn)的配置文檔,Seam用它來(lái)將其攔截器添加到JSF生命周期中。

    <faces-config>

    <lifecycle>
    <phase-listener>
    org.jboss.seam.jsf.SeamPhaseListener
    </phase-listener>
    </lifecycle>

    </faces-config>

    navigation.xml文檔為多頁(yè)面應(yīng)用包含JSF頁(yè)面導(dǎo)航規(guī)則。因?yàn)閔ello world示例只有一個(gè)簡(jiǎn)單的頁(yè)面,因此該文檔是空的。

    components.xml文檔包含Seam特有的配置選項(xiàng),除jndi-pattern屬性以外,其他都不依賴于應(yīng)用。該屬性必須包括EAR文檔的名稱,以便Seam通過(guò)其的JNDI全名訪問(wèn)EJB3 bean。

    <components ...>

    <core:init
    jndi-pattern="helloworld/#{ejbName}/local"
    debug="false"/>

    <core:manager conversation-timeout="120000"/>

    </components>

    5.2. Seam組件JAR包

    app.jar文檔包含所有的EJB3bean 類(實(shí)體bean和會(huì)話bean)以及EJB3相關(guān)的配置文檔。

    app.jar
    |+ Person.class // entity bean
    |+ Manager.class // session bean interface
    |+ ManagerAction.class // session bean
    |+ seam.properties // empty file but needed
    |+ META-INF
    |+ ejb-jar.xml
    |+ persistence.xml

    seam.properties文檔這兒是空但必需的,因?yàn)镴boss要通過(guò)它知道此JAR文件包含Seam EJB3 bean類,并且相應(yīng)地處理注解。

    ejb-jar.xml文檔包含額外的配置信息,這些信息能重載或者增補(bǔ)EJB3 bean上的注解。在一個(gè)Seam應(yīng)用中,它能將所有的EJB3 類加入Seam攔截器。我們能在所有的Seam應(yīng)用中重用該文檔。

    <ejb-jar>
    <assembly-descriptor>
    <interceptor-binding>
    <ejb-name>*</ejb-name>
    <interceptor-class>
    org.jboss.seam.ejb.SeamInterceptor
    </interceptor-class>
    </interceptor-binding>
    </assembly-descriptor>
    </ejb-jar>

    persistence.xml文檔為EJB3 實(shí)體bean配置了后臺(tái)數(shù)據(jù)源。本例中,我們只是使用了被嵌入到JBoss AS中默認(rèn)的HSQL數(shù)據(jù)庫(kù)(也就是java:/DefaultDS數(shù)據(jù)源)。

    <persistence>
    <persistence-unit name="helloworld">
    <provider>
    org.hibernate.ejb.HibernatePersistence
    </provider>
    <jta-data-source>java:/DefaultDS</jta-data-source>
    <properties>
    <property name="hibernate.dialect"
    value="org.hibernate.dialect.HSQLDialect"/>
    <property name="hibernate.hbm2ddl.auto"
    value="create-drop"/>
    <property name="hibernate.show_sql" value="true"/>
    </properties>
    </persistence-unit>
    </persistence>

    這樣,以上就是一個(gè)簡(jiǎn)單Seam應(yīng)用所需的所有配置和打包。我們將在以后討論到本書(shū)的更高級(jí)的主題時(shí),涵蓋更多的配置選項(xiàng)和類庫(kù)。再次強(qiáng)調(diào)一下,Seam應(yīng)用入門(mén)最簡(jiǎn)單的方法就是,不要擔(dān)心這些配置文件,只需要從已有的應(yīng)用模板做起。

    6. 為何這么簡(jiǎn)單?

    這就是hello world 應(yīng)用,三個(gè)簡(jiǎn)單的Java類,一個(gè)JSF頁(yè)面,一組靜態(tài)配置文件。我們已經(jīng)有了一個(gè)完整的數(shù)據(jù)庫(kù)驅(qū)動(dòng)的web應(yīng)用。整個(gè)應(yīng)用只需要的是少于30行的 Java代碼,沒(méi)有一處“XML代碼”。但是如果開(kāi)發(fā)者有PHP背景,你可能仍然會(huì)問(wèn)“何以這么簡(jiǎn)單?我能在php中使用更少的代碼嗎?”

    好吧,答案就是Seam應(yīng)用在理論上要比PHP(或者其他任何一種腳本語(yǔ)言)應(yīng)用簡(jiǎn)單的多。Seam 組件模式允許我們,有所控制地,可維護(hù)地給應(yīng)用增加更多的功能。我們很快就會(huì)發(fā)現(xiàn),Seam組件使開(kāi)發(fā)有狀態(tài)的和有事務(wù)的web應(yīng)用變得易如反掌。對(duì)象關(guān) 系映射框架(例如:實(shí)體bean)允許我們將注意力放在抽象數(shù)據(jù)模型上,而不需要處理數(shù)據(jù)庫(kù)特有的SQL語(yǔ)句。

    本文是基于該書(shū)的第一章和第二章。后面的章節(jié)中,我們繼續(xù)討論如何使用Seam組件繼續(xù)開(kāi)發(fā)復(fù)雜的Seam 應(yīng)用。參見(jiàn)本書(shū)目錄來(lái)查看本書(shū)的所有主題。

    請(qǐng)看Gavin King的兩個(gè)訪談錄來(lái)查看以往關(guān)于Seam的話題。

    • JBoss Seam 1.1 Indepth: An Interview with Gavin King
    • JBoss Seam 1.0: rethinking web application architecture

    關(guān)于作者

    Dr. Michael Yuan是JBoss Seam: Simplicity and Power Beyond Java EE 5.0一書(shū)的作者。該書(shū)探討了下一代web應(yīng)用框架。他同時(shí)也是Nokia Smartphone Hacks一書(shū)和其他三本技術(shù)讀物的作者。Michael潛心研究輕量級(jí)企業(yè)web應(yīng)用,終端對(duì)終端的移動(dòng)應(yīng)用開(kāi)發(fā)。你可以通過(guò)他的博客聯(lián)系他。

    查看英文原文:Introduction to JBoss Seam
    posted on 2009-01-15 15:30 seal 閱讀(316) 評(píng)論(0)  編輯  收藏 所屬分類: Seam
    主站蜘蛛池模板: 精品在线免费观看| 亚洲爆乳少妇无码激情| 久久精品国产亚洲麻豆| 在线播放亚洲第一字幕| 亚洲亚洲人成综合网络| 亚洲午夜国产精品无码| 亚洲爆乳精品无码一区二区三区| 亚洲中文字幕日产乱码高清app| 亚洲精品一级无码中文字幕| 亚洲人成网站色在线入口| 亚洲精品国产精品乱码不卞| 久久久久亚洲AV无码专区网站| 国产乱辈通伦影片在线播放亚洲 | 免费人成在线观看网站品爱网| 午夜无码A级毛片免费视频| 蜜桃成人无码区免费视频网站| 最近2019中文字幕免费大全5 | 羞羞视频在线观看免费| 2022免费国产精品福利在线 | 亚洲欧好州第一的日产suv| 亚洲国产成人精品无码区二本| 国产成人亚洲精品电影| 国产大片免费天天看| 嫩草在线视频www免费看| 1a级毛片免费观看| 成年女人免费视频播放77777| 国产一级淫片免费播放电影| 狠狠亚洲狠狠欧洲2019| 亚洲视频免费在线看| 四虎必出精品亚洲高清| 日日摸夜夜添夜夜免费视频| 两个人看的www免费| 成人免费黄色网址| 国产资源免费观看| 亚洲一区爱区精品无码| 亚洲jjzzjjzz在线观看| 在线观看亚洲网站| 免费无码又爽又刺激高潮视频| 最近2019中文免费字幕| 亚洲片国产一区一级在线观看 | 亚洲高清无码专区视频|