現在Java領域各種技術百花齊放,名目繁多,如何根據自己的需求選擇這些框架呢?特別對於初學者,在學習選擇方向上也非常迷茫,如何有針對性的根據自己項目特點進行學習就變的更加重要。
下面我們從一個發展角度來對J2EE/Java EE的這些框架誕生進行一番考量,可能對我們的選擇有很大幫助。
首先我們需要明白一個高質量的J2EE系統是什麼樣子?高質量的J2EE/Java EE系統標准實際就是OO設計的標准,松耦合是OO設計的主要追求目標之一,那麼無疑解耦性成為衡量J2EE/JEE質量的首要標准。實際選擇中,還需要兼顧可伸縮性/性能/開發效率等方面綜合考慮。
J2EE/Java EE號稱多層結構,為什麼多層比兩層好?因為多層結構解耦性好,帶來維護拓展方便靈活。
典型的J2EE/Java EE至少劃分三個層次:表現層/業務邏輯組件層/持久層。
表現層英文是Presentation Layer,是實現顯示功能的,這部分一般使用B/S結構來完成,當然你也可以使用專門遠程客戶端來實現;
業務邏輯層因為是由大量組件(Components)組成的,也可稱為組件層,組件從不同角度又可分為各種類型,然後又有不同的流派,目前占主要位置的是Model+Service,模型加服務,所以這一層又稱為業務服務層Business Service;也有稱為Model業務層;
持久層是負責對象持久化也就是數據庫操作的層次,英文Persistence Layer。
SUN伙伴們推出J2EE標准時,分別對這三個層次規定了標准實現,表現層使用JSP/Servlet技術;業務組件層使用EJB的會話Bean;持久層使用實體Bean。同時,標准將業務層和持久層在物理上組成一個新的容器EJB容器,與表現層技術完全一樣的容器,這樣,J2EE技術被細化為Web和EJB,物理上有Web容器和Web應用程序;以及EJB容器和EJB應用程序。
當然,J2EE/JEE的發展不止這些,這三個層次技術分別獨立發展,高歌猛進,下面分別單獨陳述,當你了解某種框架技術為什麼誕生時,你可能就知道你該在什麼情況下選擇它們了,工具總是因目的而生!
表現層框架
J2EE/Java EE雖是多層結構,但它不是一種強制性多層結構,也就是說,你也可能做成傳統兩層結構,有的初學者直接使用JSP嵌入Java代碼調用數據庫這樣結構實際不是多層結構,還是以前的兩層結構。
在Jsp中嵌入大量代碼,一旦報空指針錯誤就很難找出問題,很多初學者下載JiveJdon 2.5後就經常碰到這個問題,因此大量有關空指針錯誤問題出現論壇裡,為什麼他們不能自己解決呢? 那是因為無法定位錯誤在Jsp中的位置,Tomcat等服務器只告訴我們錯誤在index_jsp.java(JSp的java文件)位置,搞得一些人經常會跑到Tomcat服務器內部翻找JSP的Java文件,這一過程無比痛苦(為了減少初學者這種痛苦,本站暫停了JiveJdon2.5的下載)。
J2EE/Java EE的發展就是降低這種痛苦,首先想到的方式是:在JSp調試上下苦功,要求Tomcat等服務器提供詳細的錯誤定位;可惜到Tomcat 5.5我們也沒看到這種功能;實際上,根本解決之道就是將JSP的調試變成Java組件的調試。
首先通過MVC模式規定JSP只能等同於Html,不能包含Java代碼,將JSP和Java代碼分離,可是這樣分離之後,它們結合起來又麻煩了,所以,雖然你使用MVC模式,但是還是直接基於JSP技術,帶來的是開發效率的降低。
Struts框架解決了這個問題,通過ActionForm可以將JSp和JavaBeans方便快速地結合起來,但是有人又抱怨Struts的ActionForm限制太死,與JSP雖能對應,只能一個ActionForm一個表單對應,而不能任意組件JavaBeans都可以和JSP任意字段對應,這時就出來了組件型框架JSF/Tapestry。
表現層框架Struts/Tapestry/JSF架構比較
業務邏輯層框架
可伸縮性
因為EJB標准的推出,業務組件層以前基本是EJB的天下,但是EJB功能實在太強大,它考慮了世界頂級大型系統需求,因此免不了顯得很復雜,當初,基本上所有的大型企業高端都是選用J2EE,選用J2EE實際是選用EJB。EJB強調的高可伸縮性為大型企業日益發展提供最大的發展空間,不再因為企業快速發展導致整個企業系統結構都要發生根本變化,這是使用EJB的現實優勢。
這種企業系統的可伸縮性不是因為EJB存在才顯得重要,而是我們企業架構選擇需要考量的基本因素。換句話說,無論我們使用EJB與否,這個問題都需要考慮:一台服務器不夠用怎麼辦?如果這台服務器死機會對企業運營帶來什麼影響?如果每個星期這台服務器停機維護升級會不會對企業帶來打擊?我的企業系統是不是需要可靠的、幾乎不當機的7x24運行?當企業系統面對大量外部訪問用戶時,一台服務器是否夠用?多台服務器聯動的需求是否涉及軟件技術更換?
在這個現實因素考量後,如果覺得不是很重要,或者說將來一段時間內這些因素無所謂,那麼可以不選用EJB了。
為什麼有不選用EJB的理由?因為它復雜,學習起來比較困難,EJB幫助我們考慮企業中可能碰到的大部分問題,實際上,有的我們不需要,這也就是為什麼說EJB是一個重量級解決方案所在。
與重量級相比的是輕量,業務組件層輕量級解決方案有Spring/HiveMidn/Jdon Framework等,輕量一詞曾經因為EJB的出現而變得時髦,給人造成的感覺是:EJB花了老鼻子力氣完成的那些功能,使用我輕量級解決方案可以輕而易舉也能解決,舉重若輕啊,其實這是一種誤解。
當曾經以輕量自居的Spring將事務機制納入自己懷抱中時,它也開始低調輕量了,實際是不輕不重了;當然如果它把分布式計算和事務再次加入時,天平砝碼也會沉下去的。
初學者總是願意使用簡單的解決方案,學習使用方便,因此比較喜歡輕量級框架技術,這是正常的,但是在使用輕量級別框架之前必須明白:你的系統將來真的只需要一台服務器即可?你的項目完成期真的非常緊急?
如果只需要一台巨強服務器,就不必選擇EJB,EJB是因分布式多服務器而生,對於單台服務器,缺乏本地透明性,也就是說:你無法透過EJB直接和本地JVM或文件系統等打交道,透明性也是衡量一個框架的重要指標。
當然,重量和輕量並不完全對立,EJB3就是為了簡化J2EE的使用,使得EJB不只是擅長處理大型企業系統,中小型系統也使用很方便,這實際上也是EJB輕量化的一種努力。什麼是Java EE 5?
所以,對於架構選擇來說,根本前提是需要明白你的系統現在或將來一段時間(注意需要考慮將來一段時間,不能只看眼前)是中小型系統還是大型系統?
靈活性/定制性/透明性
當然這個答案有時我們自己也可能很難給出,那麼我們還需要從其他角度來考量EJB和非EJB之選,例如筆者曾經經歷一個大型實時娛樂平台社區系統,從規模上說肯定是大型系統,設計目標10萬人在線,從這個角度非選用EJB不可!
但是,EJB因為還有事務機制,雖然應用程序可以選擇失效EJB事務,但是EJB容器設計因為考慮了事務,所以在其內核上總是會顯得臃腫,是一種累贅,這也是一種重量表示,不需要的東西存在肯定會影響效率,那麼難道我不能根據我的需求,對EJB整體包括EJB容器進行可配置式的切割?也就是說,我上面這個案例只需要EJB的分布式計算功能,其他的功能我都拆除,只剩余我需要的功能能運行就可以了,輕裝上陣。
可惜,這種任意切割,應需而定的目標在EJB3標准還沒有被重視,所幸的是,Ioc/AOP技術為這種目標實現提供了實現可能,但是,只有Ioc/AOP還是不夠,特別是看Ioc的范圍,如果你只把應用系統組件納入Ioc管理時,自由解耦只屬於應用系統,我上面案例的目標還是無法達到,當你把框架本身組件也納入Ioc管理時,任意切割,應需而定的目標才真正實現。
Spring和EJB3屬於“只把應用系統組件納入Ioc管理”,這從JBoss 4.0版本可以看出;那什麼框架會把框架本身組件也納入Ioc管理呢?apache的Hivemind和筆者開發的Jdon框架。
什麼樣的組件可以被納入Ioc管理呢?POJO組件,POJO這個概念其實當初是針對EJB缺點而推出,EJB要求應用系統的組件必須繼承或依賴EJB容器,這樣使得調試變的不方便,但是後來,POJO的概念已經不只最初這些概念,POJO代表那種與周圍完全脫離關系、自由自在的Object了,如果應用系統的Model或者Service都是POJO,意味著你的應用系統不依賴任何其他系統,解耦性靈活性高。
POJO是因為EJB而提出的,當EJB自己傾向POJO時,大家都在宣稱自己是POJO時,POJO概念就沒有立足點了,這也是Java領域哭笑不得的現象,但是我個人更傾向把非EJB的JavaBeans組件通稱為POJO。
Hivemind的Ioc依賴注射部分功能和Jdon框架非常類似,當上百個POJO組件配置時,完全不必指定它們之間的依賴關系;你可以將自己應用程序的組件注冊到Registry中,這樣Hivemind將幫助你啟動這些組件,正如你在Jdon框架中將你的組件寫入mycontainer.XML中,Jdon框架也將自動啟動你這些組件,並解決它們之間的互相調用,包括和框架本身組件互動。
HiveMind和Jdon框架定義的POJO Service有如下特點:
不象EJB那樣缺乏本地透明化(location transparency)概念,這些POJO Service總是能定位到同樣一個JVM;也不象基於XML的Web服務web services那樣沒有語言透明(language transparency)概念,這些POJO Service總是可以被一組Java接口來概括替代(通過調用Java interface來替代調用這些具體Service);當然,更不會類似JMX或Jini,不能進行service的熱裝載( hot-loading)。
注意:當Ioc/AOP提供高度靈活的同時,已經有初學者開始抱怨Spring的過分靈活,那麼比Spring在組件上更靈活的Jdon框架只能算是一種追求極端,它不一定構成你進行架構選擇的主要依據!
上面這些討論只是表明在靈活性(解耦性/透明性)這條需求道路上深究下去的選擇,你自己的應用系統需求會產生各種不同的要求,有些要求甚至是極致的,這種偏向程度就成為你架構選擇的目標,如果你的這種極致要求在目前Java世界裡還沒有可選框架時,那麼你就要動手自己做了,這也說明什麼時候你開始自己做框架(如Jdon框架),雖然在大多數情況下我們是不必要自己發明輪子的。
快速構建性
前面是從靈活性和定制性這個角度討論架構選擇目標,但是在一般情況下,我們還是從上手難易、開發效率這個角度來進行架構選擇,從這個角度來說,就是需要我們將選用的框架盡可能的多幫助我們實現一些功能,但這又是和使用難易是矛盾的,因此有個取捨問題,取捨有個准則:這個框架盡量能提供越多功能;盡量需要我們少寫代碼,甚至不寫代碼(使用XML配置),少動腦筋。
關於XML配置這裡也涉及難易問題,XML配置語法不能太復雜,有太多小開關Switch也增加學習成本。
從這個角度看,EJB無論是EJB2或EJB3提供的功能是最齊全的,但是XML配置開關太多 ,Spring屬於中等,組件XML配置不算簡單,但是因為有不少Struts+Spring+Hibernate之類現成開源代碼可供參考,因此學習起來難度也不大,Spring越來越象一個J2EE API(注意,JDK是J2SE API) ,Spring除不能提供分布式計算外,也因為過分靈活降低了一些開發效率,例如它的組件依賴關系一般需要逐步指定,auotwiring功能還沒有深入骨髓成為核心功能。Ioc容器的革命性優點。
Spring除了提供組件層功能以外,還有表現層支持Spring MVC;也有持久層實現的JDBC模板,這樣,整個J2EE/Java EE系統各個層次Spring都提供了缺省實現,在這方面無疑提高了開發效率,但是Spring提供豐富API目的好像不是為了快速開發,而是為了建立一個完整的功能齊全的API功能庫。正如它網頁上開頭文字所述:As the leading full-stack Java/J2EE application framework,注意full-stack(完整齊全)是它突出的名詞。
那麼,還有另外一個空白,就是以開發效率為主要考慮,這類框架除了必須考慮足夠靈活性和豐富功能以外,宗旨是為了在一般缺省情況下快速完成一個J2EE/Java EE系統,這非常類似MDA工具了,但是一個完全喪失靈活性和定制性的MDA工具也不是我們歡迎的。
Jdon框架的發展目標是為了填補這個空白,相信也會越來越多框架向這個目標邁進,當然不可否認,Spring也可能調轉槍頭走入這個領域,EJB2/EJB3正依靠JBuilder等這樣商業化開發工具向這個領域靠攏,這個發展方向實際是4GL RAD Tools。
很多人在快速構建方面也很早進行了探索,湧現出各種工具:如何構建一個快速業務構件平台? 但是如何把快速構建和構件(組件)靈活性有機結合在一起?它是考驗一個業務構件(業務組件)平台好壞的准則。有些構件平台雖然開發迅速,但是對於特殊情況,可供程序員定制透明操作部分不多,很死,典型的是兩層結構以前的Delphi,開發很快速,但是無法象J2EE這樣深入到系統各個層次進行定制/維護/拓展!
業務組件框架對比
EJB2/EJB3 Spring Framework 1.x Jdon Framework 1.x
靈活性
(松耦合) EJB3比EJB2更具靈活性,EJB3支持應用系統POJO 支持應用系統POJO,框架基礎功能不能替換 支持應用系統POJO,框架本身可分離配置,定制性更強
功能完整性 全面,支持異步JMS 分布式事務 較為全面。有自己的表現層和持久層模板,可支持異步 基本完整,表現層借助Struts實現。有自己簡單的持久層模板
領域范圍支持業務邏輯Session 不支持,需要開發者額外基於ThreadLocal編制代碼,耗費精力和時間。 支持業務邏輯Session
Ioc/AOP支持 EJB3支持Ioc, JBoss等EJB3服務器支持AOP;基於業務組件的較粗粒度 基於JavaBeans類的細粒度;一般小型應用過於靈活帶來復雜。 基於業務組件的較粗粒度
Ioc是否支持autowiring EJB3支持 缺省不支持,可設置支持 缺省支持
單台性能 一般,批量查詢等大數據量業務處理須小心,存在本地不透明缺陷。 一般,框架本身組件無性能提升極致,應用程序可配置cache/Pool 好,框架本身組件使用緩存提升性能,應用程序可配置cache/Pool,批量查詢專門優化,適合實時性並發性要求較高應用
可伸縮性可支持多台服務器分布式計算。不支持,可依靠EJB實現
開發效率 學習曲線長,導致熟練掌握難。借助商業開發工具可加快熟練者的開發速度。 較為復雜,可挑選只適合自己的功能實現。當組件很多時,需要照顧這些組件之間調用關系。 簡單快速,表現層編碼很少。當組件個數很多時,無需照顧它們之間的調用關系
系統規模 EJB2適合大型系統;EJB3適合中大型系統 適合中小型系統 適合小中型系統,建立一個簡單的網站系統等,和EJB無縫結合,可借助EJB支持中大型系統
重量級別重量,正在減肥 輕量偏重,有可能繼續增肥 最輕量,恪守簡單快速原則
持久層框架
持久層框架目前有EJB2/EJB3的實體Bean、Hibernate和各種JDO產品,當然還有直接寫SQL語句的JDBC,如iBatis等。
持久層框架質量好與壞區分就是是否是O/R Mapping,也就是對象和關系數據庫映射,關系數據庫需要實現定義好Schema結構;對象因為字段而變的也有一個自己的結構,如何將對象數據自動持久化到數據庫中,首先我們得定義兩者結構的對應,這實際是數據的元數據定義。
因為Hiberante/Toplink/JDO這樣O/R Mapping工具幫助你實現對象和數據庫轉換,克服了對象和數據庫阻抗現象,O/R Mapping總結 ,所以才使得我們更多的可以對象方式(從模型Model對象)來考慮Java EE/J2EE系統,可以完全放棄以前那種以數據庫為中心的思維方式:數據庫時代的終結。
所以,是否選用好的持久層框架,取決於你整個團隊思維是否徹底OO了,是否需要真正OO,當然,對於一些小型項目,有時我們覺得直接使用JDBC模板反而更加輕松快捷一點,這也是Spring的JDBC模板/iBatis/Jdon的Jdbc模板存在的理由了。
例如新增一個數據表,在Jdon框架只需要下面幾行代碼即可:
String sql = "INSERT INTO testuser (userId , name) VALUES (?, ?)";
List queryParams = new ArrayList();
queryParams.add(userTest.getUserId());
queryParams.add(userTest.getName());
jdbcTemp.Operate(queryParams,sql);
這種方式和O/R Mapping興師動眾的多個XML配置和關系映射思考相比,對於習慣SQL語句的程序員反而更加迅速。
從以上可以看出,靈活性/快速性/簡單性/可伸縮性是我們進行架構選擇的主要幾個依據,架構選擇實際就是在這幾個策略之間做一個平衡。當然,還有一個非常重要的因素,因為它不屬於某個層次的技術,性能/緩存是必須和上面因素綜合考慮的因素。