J2EE開(kāi)發(fā)框架
Rod Johnson
Java2企業(yè)版為中間件領(lǐng)域思想的統(tǒng)一上發(fā)揮了很大的作用。比如,J2EE為分布式事務(wù)管理、目錄服務(wù)和消息服務(wù)提供了一套標(biāo)準(zhǔn)的編程接口。J2EE的基礎(chǔ)——Java2標(biāo)準(zhǔn)版(J2SE) ,成功地為Java提供了一套訪(fǎng)問(wèn)關(guān)系數(shù)據(jù)庫(kù)的標(biāo)準(zhǔn)。
但是,就像本文中“J2EE缺乏對(duì)編程的支持”提到的一樣,J2EE這個(gè)平臺(tái)沒(méi)有能夠提供一個(gè)令人滿(mǎn)意的應(yīng)用程序編程模型(application programming model)。Sun公司和一些大的應(yīng)用服務(wù)器供應(yīng)商都想用開(kāi)發(fā)工具來(lái)降低J2EE開(kāi)發(fā)的復(fù)雜性,但是這些工具沒(méi)有其他的JAVA 開(kāi)發(fā)工具優(yōu)秀,后者有先進(jìn)的重構(gòu)工具,和.NET平臺(tái)相比,J2EE的工具支持顯得很遜色。
很多J2EE開(kāi)發(fā)工具自動(dòng)產(chǎn)生的代碼像這些工具本身同樣復(fù)雜。在開(kāi)源社區(qū)很多小型J2EE開(kāi)發(fā)者選擇了另外一種開(kāi)發(fā)方式—— 一些可以降低J2EE開(kāi)發(fā)難度的開(kāi)發(fā)框架,較為流行的比如: Struts, Hibernate, 和 Spring Framework,他們當(dāng)今很多J2EE項(xiàng)目種扮演著重要角色。
為什么要采用框架?
框架是一由一些類(lèi)組成,正式這些類(lèi)為應(yīng)用程序提供了一個(gè)可重用的設(shè)計(jì)――或者我們經(jīng)常提到的——應(yīng)用程序種的一層。應(yīng)用程序代碼訪(fǎng)問(wèn)類(lèi)庫(kù)從而執(zhí)行任務(wù),而框架是調(diào)用應(yīng)用程序代碼,從而管理程序的流程。這就是經(jīng)常說(shuō)道的好萊塢原則:“不要試圖聯(lián)系我們,我們到時(shí)候自會(huì)通知你。”開(kāi)發(fā)者寫(xiě)的程序在運(yùn)行時(shí)由框架調(diào)用。
設(shè)計(jì)一個(gè)在各種未知背景下都可以使用的框架是很有挑戰(zhàn)性的??蚣芎苓m合在復(fù)雜的J2EE開(kāi)發(fā)中使用,它可以為開(kāi)發(fā)者提供一個(gè)簡(jiǎn)單易用的模型。采用一個(gè)經(jīng)過(guò)良好設(shè)計(jì)的開(kāi)源框架有很多好處:
在好的框架下,開(kāi)發(fā)者只需要寫(xiě)一些必須的代碼;他們不需要直接接觸底層的API。 這一點(diǎn)很重要。
經(jīng)過(guò)良好設(shè)計(jì)的框架可以為程序提供清晰的結(jié)構(gòu)并且提高程序的內(nèi)聚性。好清晰的結(jié)構(gòu)使得其他人可以更容易加入項(xiàng)目。
一個(gè)容易使用的框架可以通過(guò)一些例子和文檔為用戶(hù)提供最佳實(shí)踐。
采用成功的框架的代碼比自己的代碼容易測(cè)試
框架只有提供了一些值得使用的功能才會(huì)變得流行。J2EE工程只有真正需要框架的時(shí)候才會(huì)用它,而自己的框架并不是這樣,后者是處于統(tǒng)治地位的。
J2EE本身也提供了一些框架。比如, Enterprise Java-Beans (EJB) container或者 Servlet engine,二者都運(yùn)用了“ 采用了好萊塢原則”這個(gè)思想,并采用運(yùn)行時(shí)調(diào)用來(lái)管理對(duì)象。像Struts這些開(kāi)源web應(yīng)用框架正式建立在這兩個(gè)框架的基礎(chǔ)上的,本文討論的重點(diǎn)也是像Struts這樣建立在J2EE上的框架,他們?yōu)殚_(kāi)發(fā)者提供了更為簡(jiǎn)單的模型,和其他的一些好處。
開(kāi)源框架的出現(xiàn)。
很多大型的J2EE項(xiàng)目都用自己的內(nèi)部框架來(lái)隱藏平臺(tái)的復(fù)雜性,直到最近人們才逐漸發(fā)現(xiàn)一些在很多項(xiàng)目中都存在的共有的難題,這些難題都可以由一個(gè)較為統(tǒng)一的解決方案來(lái)解決。而有的框架正好可以充當(dāng)這些問(wèn)題的解決方案?,F(xiàn)在有種很明顯的趨勢(shì):與從前的內(nèi)部框架相比,這些框架將成為這些難題的更加“標(biāo)準(zhǔn)化 ”的解決方案。
J2EE平臺(tái)的日益成熟是這些框架流行的一個(gè)原因。開(kāi)發(fā)者知道有些地方是J2EE的標(biāo)準(zhǔn)API無(wú)能為力的,倚他們的經(jīng)驗(yàn)來(lái)看,要彌補(bǔ)這個(gè)缺陷是很困難的。于此同時(shí),一些優(yōu)秀的開(kāi)源框架可供使用,它們提供了極為豐富的技術(shù)文檔,在它們背后還有一個(gè)專(zhuān)業(yè)的團(tuán)隊(duì)做支持,并且一切都是免費(fèi)的。
Struts。在web應(yīng)用程序產(chǎn)生的那時(shí)就有了開(kāi)源框架。在1999-2000年,開(kāi)發(fā)者們意識(shí)到JSP“Model1”的缺陷,JSP中充斥著請(qǐng)求處理代碼和靜態(tài)數(shù)據(jù)模板,這意味著你不得不把業(yè)務(wù)邏輯和復(fù)雜的HTML以及其他的標(biāo)簽混到一起。那個(gè)時(shí)候還沒(méi)有標(biāo)準(zhǔn)的框架和J2EE的標(biāo)準(zhǔn)支持,要解決這個(gè)問(wèn)題開(kāi)發(fā)者就得自己實(shí)現(xiàn)前端控制器,這樣可以把業(yè)務(wù)邏輯分離到java類(lèi)中,從而可以減輕對(duì)JSP的維護(hù)難度。前端控制器模式經(jīng)常運(yùn)用在MVC架構(gòu)中,MVC模式在OO語(yǔ)言的GUI開(kāi)發(fā)中經(jīng)常使用(這個(gè)名字總是讓人誤解,WEB MVC中的視圖是從模型中“拉”數(shù)據(jù);而在經(jīng)典MVC中,模型把事件“推向”視圖)。
最初的前端控制器實(shí)現(xiàn)質(zhì)量參差不齊。2001~2002年間,Apache開(kāi)源組織發(fā)布的Struts改變了這個(gè)狀況,雖然它并非一個(gè)完美的框架,但已經(jīng)足夠使其成為該領(lǐng)域事實(shí)上的標(biāo)準(zhǔn)。
Struts向人們展示了開(kāi)源框架的一些優(yōu)點(diǎn),比如,新手可以很容易地熟悉它的結(jié)構(gòu)。2002年末,它成立很多J2EE項(xiàng)目很自然的選擇,每一個(gè)認(rèn)真的J2EE開(kāi)發(fā)者都會(huì)對(duì)它很熟悉。
Struts幾乎用才每一個(gè)J2EE項(xiàng)目中,這使得它成為J2EE架構(gòu)的一個(gè)重要組成部分。甚至很多保守的組織也將其作為軟件底層的一部分,并同意接受Apache的開(kāi)源協(xié)議條款。
Hibernate。下一個(gè)倒下的多骨諾米牌就是持久化。J2EE提供了兩個(gè)持久化的手段:JDBC,它是J2SE中訪(fǎng)問(wèn)關(guān)系數(shù)據(jù)庫(kù)系統(tǒng)的標(biāo)準(zhǔn)API;另一個(gè)是實(shí)體Beans ,它是EJB中專(zhuān)門(mén)模型化持久化實(shí)體的組件。
JDBC以一種錯(cuò)誤的編程模型來(lái)強(qiáng)制開(kāi)發(fā)者用Java代碼來(lái)處理關(guān)系思想。而實(shí)體beans,先不說(shuō)Sun和其他主要的J2EE供應(yīng)商的吹噓,給人很笨重的感覺(jué):起初這門(mén)技術(shù)的應(yīng)用范圍很窄,連持久對(duì)象間的關(guān)系都不能處理。它使得應(yīng)用程序難于測(cè)試,并且使用了一個(gè)很糟糕的查詢(xún)語(yǔ)言。直到2003年,即使EJB2.0和2.0做了很多改進(jìn),開(kāi)發(fā)者們卻很少用它。
早期的嘗試。
持久化問(wèn)題的解決方案是由關(guān)系-對(duì)象映射(ORM)來(lái)解決的,它可以透明地持久化普通java對(duì)象(POJO)。該思想在注釋中有解釋。雖然這種方案并不是專(zhuān)屬java的。但相對(duì)與其他的社區(qū)而言比如.NET,ORM在java社區(qū)更加流行(.NET開(kāi)發(fā)者總是對(duì)之抱有懷疑的態(tài)度)。
早在1990年,一些商業(yè)的ORM工具就出現(xiàn)了,比如TopLink。但由于其價(jià)格昂貴、結(jié)構(gòu)復(fù)雜并且與Sun的實(shí)體bean標(biāo)準(zhǔn)相左,所以很少人會(huì)用。不管怎樣,在持久化POJO方面,這些工具與JDBC和實(shí)體Bean相比確實(shí)有了很大的進(jìn)步
Java Data Object于2001年在Java Community Progress(www.jcp.org)的規(guī)范中出現(xiàn)。它為一般的POJO提供了大多數(shù)的持久化實(shí)現(xiàn)(盡管很多實(shí)現(xiàn)都是對(duì)關(guān)系數(shù)據(jù)庫(kù)的)。但Sun公司以及其他的J2EE技術(shù)提供商對(duì)該技術(shù)表現(xiàn)的很冷淡。所以JDO也沒(méi)有能夠流行。
Hibernate的出現(xiàn)。ORM領(lǐng)域在2002年發(fā)生了大變化,原因有兩個(gè)。首先,實(shí)體Beans在實(shí)踐中失敗,開(kāi)發(fā)者們將其從J2EE中忽視掉了。它向開(kāi)發(fā)者們說(shuō)明了一個(gè)規(guī)范是如何將開(kāi)發(fā)拉入泥潭的。
另外的一個(gè)原因是Hibernate的發(fā)布,它是第一個(gè)功能健全的解決關(guān)系對(duì)象影射解決方案。雖然在功能上,它沒(méi)有TopLink多樣。但在那些最常用的功能上,Hibernate實(shí)現(xiàn)的更加健壯,并且有一個(gè)非常專(zhuān)業(yè)的團(tuán)隊(duì)提供全職的開(kāi)發(fā)。Hibernate并不是全新的,它的ORM思想在這個(gè)領(lǐng)域很普遍,但它提供的編程模型比其他任何競(jìng)爭(zhēng)者都容易使用、都來(lái)的直接,它為ORM的使用提供了更加易用、廉價(jià)的途徑。
于此同時(shí),新一代的商業(yè)產(chǎn)品針對(duì)關(guān)系數(shù)據(jù)庫(kù)提供了極其高效的JDO規(guī)范的實(shí)現(xiàn)。這樣開(kāi)發(fā)者的選擇就更豐富了;還有,TopLink也朝著開(kāi)發(fā)者友好的方向前進(jìn),它的liscense越來(lái)越開(kāi)放了。
ORM大獲全勝。
所的這些因素是的ORM比以往更加規(guī)范。雖然很多項(xiàng)目仍然使用自己的持久層框架,但Hibernate,TopLink以及一些高端的JDO實(shí)現(xiàn),使得使用自己持久層框架的難度相對(duì)變大、可維護(hù)性降低,自然,也沒(méi)有什么理由去使用自己的框架了。
雖然這些框架的功能覆蓋范圍已經(jīng)很大了,但仍有很多地方不在其中。比如,一個(gè)基于struts,hibernate的項(xiàng)目,業(yè)務(wù)邏輯很難搞定。盡管對(duì)于這種問(wèn)題,J2EE規(guī)范提出了解決方案(EJB),但仍舊沒(méi)有一個(gè)合適的編程模型。
Spring
J2EE框架被大規(guī)模地運(yùn)用到項(xiàng)目中,而項(xiàng)目總要負(fù)責(zé)這些框架以及自己業(yè)務(wù)代碼的連接,使之真正融合到一起。Spring就是專(zhuān)注于這個(gè)問(wèn)題的,它和Hibernate融合的很好。
本質(zhì)上講,Spring是IOC(Inversion of Control)和面向切面編程(AOP)的組合體。它是一個(gè)非侵入式的框架,增強(qiáng)了POJO的功能。從服務(wù)上講(With a service abstraction),它將程序代碼從J2EE環(huán)境解耦到普通的java對(duì)象(自然,這些代碼可以脫離J2EE而在多種環(huán)境中運(yùn)行)。它還在很多功能上提供了除EJB之外的選擇――比如為所有的POJO提供聲明式事務(wù)。Spring被廣泛運(yùn)用到很多項(xiàng)目中,從小的web程序到大的企業(yè)應(yīng)用程序。
在這個(gè)領(lǐng)域還有其他的產(chǎn)品,比如HiveMind和NamoContainer。前者和Spring的思想大致相同,只不過(guò)在IOC上有較大差異;后者將很多服務(wù)融合在PicoContainer的IOC容器中。這些產(chǎn)品的實(shí)現(xiàn)方式和J2EE的不同在于,它們都很輕便。
在有J2EE API下做測(cè)試是非常困難的,這些容器將POJO從J2EE API中脫離出來(lái),從而大大降低了測(cè)試的難度。測(cè)試一個(gè)普通的java對(duì)象,不用象測(cè)試J2EE程序那樣,得先將應(yīng)用程序部署到服務(wù)器上,要不就得自己動(dòng)手模擬J2EE環(huán)境。提供日益流行的測(cè)試驅(qū)動(dòng)的開(kāi)發(fā)環(huán)境(對(duì)于開(kāi)發(fā)者來(lái)說(shuō)這是應(yīng)得的),是這些輕量容器流行的關(guān)鍵因素。
下一個(gè)將會(huì)是誰(shuí)?
人們?nèi)找鎸?duì)開(kāi)源框架的重視,使得很多項(xiàng)目的成本大大降低,并且投放使用以及維護(hù)速度都增加了?,F(xiàn)在的開(kāi)源框架都有很高的質(zhì)量,都提供了很好的文檔&一些書(shū)籍讓開(kāi)發(fā)者做參考。即便如此,兩大因素是的J2EE領(lǐng)域充滿(mǎn)了不確定性:開(kāi)源領(lǐng)域和J2EE“標(biāo)準(zhǔn)”的沖突和AOP的日益重要。
開(kāi)源和標(biāo)準(zhǔn)之間的沖突表現(xiàn)在兩個(gè)地方。一個(gè)是表現(xiàn)層,JSF的身后有Sun公司和其他的一些大公司,而在這個(gè)領(lǐng)域有Struts等開(kāi)源產(chǎn)品與之競(jìng)爭(zhēng)。在中間層,EJB 3.0采用J2SE5.0的annotations實(shí)現(xiàn)了依賴(lài)注入(dependency injection)的功能,但這個(gè)功能只是Spring的一個(gè)子集
在這兩個(gè)領(lǐng)域,開(kāi)源產(chǎn)品都更加革新。JSP借鑒了ASP.NET,而Tapestry則采用了WebObjects的思想。
同樣的,不知道EJB3.0為何要嘗試著標(biāo)準(zhǔn)化依賴(lài)注入,即使這樣會(huì)使之不可避免地喪失很多功能。 EJB 3.0好像也要進(jìn)入程序編寫(xiě)領(lǐng)域,而J2EE規(guī)范在這方面還沒(méi)有涉足。
于此同時(shí),AOP的重要性在J2EE社區(qū)猛增,在使用上,AOP也越來(lái)越受到開(kāi)發(fā)者的青睞。像Spring、dynaop等被稱(chēng)作“帶著雙拐的AOP”實(shí)現(xiàn)提升了AOP的知名度。而純粹的AOP技術(shù)比如AspectJ,在將來(lái)的幾年也會(huì)流行起來(lái)。
其次,JBoss通過(guò)JCP和EJB3.0保持一致,它極大地推動(dòng)了AOP技術(shù)。但即使如此,JCP 還沒(méi)有轉(zhuǎn)向AOP跡象。
下一代的J2EE規(guī)范將擁抱更簡(jiǎn)單的POJO編程模型,就像Spring和Hibernate做的一樣。J2EE開(kāi)發(fā)者也注定要從“欺詐客戶(hù)”轉(zhuǎn)到以自己的編程經(jīng)驗(yàn)開(kāi)發(fā)上來(lái)。這次改變將受到大多數(shù)人的歡迎,不像以前那樣每一個(gè)新規(guī)范發(fā)布后,最終都沒(méi)有能很好的實(shí)現(xiàn)。
本位作者Rod Johnson 是Interface21的CEO。該公司是位于倫敦的一家J2EE咨詢(xún)公司。他的聯(lián)系方式是:rod@interface21.com 。
編輯 Richard G. Mathieu,他是St. Louis大學(xué)Decision Sciences and MIS部門(mén)主任,他的聯(lián)系方式: mathieur@slu.edu
聯(lián)系客服