現在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中嵌入大量代碼,一旦報null 指標錯誤就很難找出問題,很多初學者下載JiveJdon 2.5後就經常碰到這個問題,因此大量有關null 指標錯誤問題出現論壇裡,為什麼他們不能自己解決呢? 那是因為無法定位錯誤在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實現 |
不支援,可依靠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語句的程式員反而更加迅速。
從以上可以看出,靈活性/快速性/簡單性/延展性是我們進行架構選擇的主要幾個依據,架構選擇實際就是在這幾個策略之間做一個平衡。當然,還有一個非常重要的因素,因為它不屬於某個層次的技術,效能/緩衝是必須和上面因素綜合考慮的因素。
因為效能最初是我們使用電腦的基本原因,別忘記這個根本。