12個最重要的J2EE最佳實踐
1. 始終使用 MVC 框架。
MVC 框架可以將業務邏輯(Java beans 和 EJB 組件)、控制器邏輯 (Servlets/Struts 動作)、表示層(JSP、XML/XSLT)清晰地分離開來。良好的分層可以帶來許多好處。
MVC 框架對于成功使用 J2EE 是如此重要,以致沒有其他最佳實踐可以與其相提并論。模型-視圖-控制器(MVC)是設計 J2EE 應用程序的基礎。MVC 將您的程序代碼 簡單地劃分下面幾個部分:
負責業務邏輯的代碼(即模型??通常使用 EJB 或者普通的 Java 對象來實現)。
負責用戶界面 顯示的代碼(即視圖??通常通過 JSP 及標記庫來實現,有時也使用 XML 和 XSLT 來實現)。
負責應用程序流程的代碼(即控制器?? 通常使用 Java Servlet 或像 Struts 控制器這樣的類來實現)。
如果您不遵循基本的 MVC 框架,在開發過程中就會出現許多的問 題。最常見的問題就是在視圖部分添加了太多的成分,例如,可能存在使用 JSP 標記來執行數據庫訪問,或者在 JSP 中進行應用程序的流程 控制,這在小規模的應用程序中是比較常見的,但是,隨著后期的開發,這樣做將會帶來問題,因為 JSP 逐步變得越來越難以維護和調試。
類似地,我們也經??吹綄⒁晥D層構建到業務邏輯的情況。例如,一個常見的問題就是將在構建視圖時使用的 XML 解析技術直接應用 到業務層。業務層應該對業務對象??而不是綁定到視圖的特定數據表示進行操作。
然而,只是具有合適的組件并不一定意味著可以使 您的應用程序得到合適的分層。我們常常見到一些應用程序包含 servlet、JSP 和 EJB 組件所有這三項,然而,其主要的業務邏輯卻是在 servlet 層實現的,或者應用程序導航是在 JSP 中處理的。您必須進行嚴格的代碼檢查并重構您的代碼,以確保應用程序的業務邏輯只在模型 層(Model layer)進行處理,應用程序導航只通過控制器層(Controller layer)進行處理,而您的視圖(Views)只是將傳遞過來的模型對 象以 HTML 及 JavaScript 的形式表示出來。
2. 在應用程序的每一層都使用自動單元測試和測試管理。
不要只是測試您的圖形用戶界面(GUI)。分層的測試使測試及維護工作變得極其簡單。
在過去的幾年中,在方法學領域有了 相當大的革新,例如新出現的被稱為 Agile(例如 SCRUM [Schwaber] 和極限編程 [Beck1])的輕量級方法現在已經得到了很普遍的應用。幾 乎所有的這些方法中的一個共同的特征是它們都提倡使用自動的測試工具,這些工具可以幫助開發人員用更少的時間進行回歸測試 (regression testing),并可以幫助他們避免由于不充分的回歸測試造成的錯誤,因此可以用來提高程序員的工作效率。實際上,還有一種被 稱為 Test-First Development [Beck2] 的方法,這種方法甚至提倡在開發實際的代碼之前就先編寫單元測試。然而,在您測試代碼之前,您 需要將代碼分割成一些可測試的片斷。一個"大泥球"是難以測試的,因為它不是只實現一個簡單的易于識別的功能。如果您的每個代碼片斷實 現多個方面的功能,這樣的代碼將難以保證其完全的正確性。?
MVC 框架(以及 J2EE 中的 MVC 實現)的一個優點就是元素的組 件化能夠(實際上,相當的簡單)對您的應用程序進行單元測試。因此,您可以方便地對實體 bean、會話 bean 以及 JSP 獨立編寫測試用例 ,而不必考慮其他的代碼?,F在有許多用于 J2EE 測試的框架和工具,這些框架及工具使得這一過程更加簡單。例如,JUnit(是一種由 junit.org 開發的開放源代碼工具)和 Cactus(由 Apache 開發的開放源代碼工具)對于測試 J2EE 組件都非常有用。[Hightower] 詳細探討 了如何在 J2EE 中使用這些工具。
盡管所有這些詳述了怎樣徹底地測試您的應用程序,但是我們仍然看到一些人認為只要他們測試了 GUI(可能是基于 Web 的 GUI,或者是獨立的 Java 應用程序),則他們就全面地測試了整個應用程序。GUI 測試很難達到全面的測試,有以 下幾種原因。首先,使用 GUI 測試很難徹底地測試到系統的每一條路徑,GUI 僅僅是影響系統的一種方式,可能存在后臺運算、腳本和各種各 樣的其他訪問點,這也需要進行測試。然而,它們通常并不具有 GUI。第二,GUI 級的測試是一種非常粗粒度的測試。這種測試只是在宏觀水 平上測試系統的行為。這意味著一旦發現存在問題,則與此問題相關的整個子系統都要進行檢查,這使得找出 bug(缺陷)將是非常困難的事 情。第三,GUI 測試通常只有在整個開發周期的后期才能很好地得到測試,這是因為只有這那個時候 GUI 才得到完整的定義。這意味著只有在 后期才可能發現潛在的 bug。第四,一般的開發人員可能沒有自動的 GUI 測試工具。因此,當一個開發人員對代碼進行更改時,沒有一種簡單 的方法來重新測試受到影響的子系統。這實際上不利于進行良好的測試。如果開發人員具有自動的代碼級單元測試工具,開發人員就能夠很容 易地運行這些工具以確保所做的更改不會破壞已經存在的功能。最后,如果添加了自動構建功能,則在自動構建過程中添加一個自動的單元測 試工具是非常容易的事情。當完成這些設置以后,整個系統就可以有規律地進行重建,并且回歸測試幾乎不需要人的參與。?
另外 ,我們必須強調,使用 EJB 和 Web 服務進行分布式的、基于組件的開發使得測試單個的組件變得非常必要。如果沒有"GUI"需要測試,您就必 須進行低級(lower-level)測試。最好以這種方式開始測試,省得當您將分布式的組件或 Web 服務作為您的應用程序的一部分時,您不得不 花費心思重新進行測試。
總之,通過使用自動的單元測試,能夠很快地發現系統的缺陷,并且也易于發現這些缺陷,使得測試工作變 得更加系統化,因此整體的質量也得以提高。
3. 按照規范來進行開發,而不是按照應用服務器來進行開發。
要將規范熟記于心,如果要背離規范,要經過慎密的考慮后才可以這樣做。這是因為當您背離規則的時候,您所做的事情往往并不是 您應該做的事情。
當您要背離 J2EE 可以允許您做的事情的時候,這很容易讓使您遭受不幸。我們發現有一些開發人員鉆研一些 J2EE 允許之外的東西,他們認為這樣做可以"稍微"改善J2EE的性能,而他們最終只會發現這樣做會引起嚴重的性能問題,或者在以后的移植( 從一個廠商到另一個廠商,或者是更常見的從一個版本到另一個版本)中會出現問題。實際上,這種移植問題是如此嚴重,以致 [Beaton] 將 此原則稱為移植工作的基本最佳實踐。?
現在有好幾個地方如果不直接使用 J2EE 提供的方法肯定會產生問題。一個常見的例子 就是開發人員通過使用 JAAS 模塊來替代 J2EE 安全性,而不是使用內置的遵循規范的應用程序服務器機制來進行驗證和授權。要注意不要脫 離 J2EE 規范提供的驗證機制,如果脫離了此規范,這將是系統存在安全漏洞以及廠商兼容性問題的主要原因。類似地,要使用 servlet 和 EJB 規范提供的授權機制,并且如果您要偏離這些規范的話,要確保使用規范定義的 API(例如 getCallerPrincipal())作為實現的基礎。通 過這種方式,您將能夠利用廠商提供的強安全性基礎設施,其中,業務要求需要支持復雜的授權規則。
其他常見的問題包括使用不遵 循 J2EE 規范的持久性機制(這使得事務管理變得困難)、在J2EE程序中使用不適當的J2SE 方法(例如線程或 singleton),以及使用您自己 的方法解決程序到程序(program-to-program)的通信,而不是使用 J2EE 內在支持的機制(例如 JCA、JMS 或 Web 服務)。當您將一個遵循 J2EE 的服務器移植到其他的服務器上,或者移植到相同服務器的新版本上,上述的設計選擇將會造成無數的問題。唯一要背離規范的情況是, 當一個問題在規范的范圍內無法解決的時候。例如,安排執行定時的業務邏輯在 EJB2.1 出現之前是一個問題,在類似這樣的情況下,我們建 議當有廠商提供的解決方案時就使用廠商提供的解決方案(例如 WebSphere Application Server Enterprise 中的 Scheduler 工具),而在 沒有廠商提供的解決方案時就使用第三方提供的工具。如果使用廠商提供的解決方案,應用程序的維護以及將其移植到新的規范版本將是廠商 的問題,而不是您的問題。?
最后,要注意不要太早地采用新技術。太過于熱衷采用還沒有集成到 J2EE 規范的其他部分或者還 沒有集成到廠商的產品中的技術常會帶來災難性的后果。支持是關鍵的??如果您的廠商不直接支持一種特定的在 JSR 中提出的技術,但此技術 還沒有被 J2EE 所接受,那么您就不應該采用此技術。畢竟,我們中的大多數人從事解決業務問題,而不是推進技術的發展。
4. 從一開始就計劃使用 J2EE 安全性。
啟用 WebSphere 安全性。這使您的 EJB 和 URL 至少可以讓所 有授權用戶訪問。不要問為什么??照著做就是了。?
在與我們合作的客戶中,一開始就打算啟用 WebSphere J2EE 安全性的顧客 是非常少的,這一點一直讓我們感到吃驚。據我們估計大約只有 50% 的顧客一開始就打算使用此特性。例如,我們曾與一些大型的金融機構( 銀行、代理等等)合作過,他們也沒有打算啟用安全性。幸運的是,這種問題在部署之前的檢查時就得以解決.
不使用 J2EE 安全性 是危險的事情。假設您的應用程序需要安全性(幾乎所有的應用程序都需要),您敢打賭您的開發人員能夠構建出自己的安全性系統,而這個 系統比您從 J2EE 廠商那里買來的更好。這可不是個好的賭注,為分布式的應用程序提供安全性是異常困難的。例如,您需要使用網絡安全加 密令牌控制對 EJB 的訪問。以我們的經驗看來,大多數自己構建的安全性系統是不安全的,并且有重大的缺陷,這使產品系統極其脆弱。
一些不使用 J2EE 安全性的理由包括:擔心性能的下降,相信其他的安全性(例如 Netegrity SiteMinder)可以取代 J2EE 安全性, 或者是不知道 WebSphere Application Server 安全特性及功能。不要陷入這些陷阱之中,尤其是,盡管像 Netegrity SiteMinder 這樣的產 品能夠提供優秀的安全特性,但是僅僅其自身不可能保護整個 J2EE 應用程序。這些產品必須與 J2EE 應用程序服務器聯合起來才可能全面地 保護您的系統。
其他的一種常見的不使用 J2EE 安全性的原因是:基于角色的模型沒有提供足夠的粒度訪問控制以滿足復雜的業務規 則。盡管事實是這樣的,但這也不應該成為不使用 J2EE 安全性的理由。相反地,應該將 J2EE 驗證及 J2EE 角色與特定的擴展規則結合起來 。如果復雜的業務規則需要做出安全性決策,那就編寫相應的代碼,其安全性決策要基于可以直接使用的以及可靠的 J2EE 驗證信息(用戶 ID 和角色)。
反復的開發工作將使您能夠逐漸地掌握所有的 J2EE 模塊。要從創建小而簡單的模塊開 始而不是從一開始就馬上涉及到所有的模塊。
我們必須承認 J2EE 是龐大的體系。如果一個開發小組只是開始使用 J2EE,這將很難 一下子就能掌握它。在 J2EE 中有太多的概念和 API 需要掌握。在這種情況下,成功掌握 J2EE 的關鍵是從簡單的步驟開始做起。 ?
這種方法可以通過在您的應用程序中創建小而簡單的模塊來得到最好的實現。如果一個開發小組通過創建一個簡單的域模型以 及后端的持久性機制(也許使用的是 JDBC),并且對其進行了完整的測試,這會增強他們的自信心,于是他們會使用該域模型去掌握使用 servlet 和 JSP 的前端開發。如果一個開發組發現有必要使用 EJB,他們也會類似地開始在容器管理的持久性 EJB 組件之上使用簡單的會話 Facades,或者使用基于 JDBC 的數據訪問對象(JDBC-based Data Access Objects,DAO),而不是跳過這些去使用更加復雜的構造(例如消 息驅動bean和JMS)。
這種方法并不是什么新方法,但是很少有開發組以這種方式來培養他們的技能。相反地,多數開發組由于嘗試 馬上就構建所有的模塊,同時涉及 MVC 中的視圖層、模型層和控制器層,這樣做的結果是他們往往會陷入進度的壓力之中。他們應該考慮一些 敏捷(Agile)開發方法,例如極限編程(XP),這種開發方法采用一種增量學習及開發方法。在 XP 中有一種稱為 ModelFirst 的過程,這個 過程涉及到首先構建域模型作為一種機制來組織和實現用戶場景?;菊f來,您要構建域模型作為您要實現的用戶場景的首要部分,然后在域 模型之上構建一個用戶界面(UI)作為用戶場景實現的結果。這種方法非常適合讓一個開發組一次只學到一種技術,而不是讓他們同時面對很 多種情況(或者讓他們讀很多書),這會令他們崩潰的。
還有,對每個應用程序層重復的開發可能會包含一些適當的模式及最佳實踐 。如果您從應用程序的底層開始應用一些模式如數據訪問對象和會話 Facades,您就不應該在您的JSP和其他視圖對象中使用域邏輯。
最后,當您開發一些簡單的模塊時,在開始的初期就可以對您的應用程序進行性能測試。如果直到應用程序開發的后期才進行性能測 試的話,這往往會出現災難性的后果。
6. 當使用 EJB 組件時,始終使用會話 Facades。
決不 要將實體 bean 直接暴露給任何用戶類型。對實體 bean 只可以使用本地 EJB 接口(Local EJB interfaces)。
當使用 EJB 組件時 ,使用一個會話 Facades 是一個確認無疑的最佳實踐。實際上,這個通用的實踐被廣泛地應用到任何分布式的技術中,包括 CORBA、EJB 和 DCOM。從根本上講,您的應用程序的分布"交叉區域"越是底層化,對小塊的數據由于多次重復的網絡中繼造成的時間消耗就越少。要達到這個 目的的方法就是:創建大粒度的 Facades 對象,這個對象包含邏輯子系統,因而可以通過一個方法調用就可以完成一些有用的業務功能。這種 方法不但能夠降低網絡開銷,而且在 EJB 內部通過為整個業務功能創建一個事務環境也可以大大地減少對數據庫的訪問次數。
EJB 本地接口(從 EJB 2.0 規范開始使用)為共存的 EJB 提供了性能優化方法。本地接口必須被您的應用程序顯式地進行訪問,這需要代碼的改 變和防止以后配置 EJB 時需要應用程序的改變。由于會話 Facades 和它包含的整個 EJB 對于彼此來說都應該是本地的,我們建議對會話 Facades 后面的實體 bean 使用本地接口。然而,會話 Facades 本身的實現(典型例子如無狀態會話 bean)應該設計為遠程接口。
為了性能的優化,可以將一個本地接口添加到會話 Facades。這樣做利用了這樣一個事實:在大多數情況下(至少在 Web 應用程序中),您的 EJB 客戶端和 EJB 會共同存在于同一個 Java 虛擬機(JVM)中。另外一種情況,如果會話 Facades 在本地被調用,可以使用 J2EE 應用服務 器配置優化(configuration optimizations),例如 WebSphere 中的"No Local Copies"。然而,您必須注意到這些可供選擇的方案會將交互 方法從按值傳遞(pass-by-value)改變為按引用傳遞(pass-by-reference)。這可能會在您的代碼中產生很微妙的錯誤。當您要利用這些方 案時,您應該在一開始就考慮其可行性。?
如果在您的會話 Facades 中使用遠程接口(而不是本地接口),您也可以將同樣的會 話 Facades 在 J2EE 1.4 中以兼容的方式作為 Web 服務來配置。這是因為 JSR 109(J2EE 1.4 中的 Web 服務部署部分)要求使用無狀態會 話 bean 的遠程接口作為 EJB Web 服務和 EJB 實現的接口。這樣做是值得的,因為這樣做可以為您的業務邏輯增加客戶端類型的數量。
7. 使用無狀態會話 bean,而不是有狀態會話 bean
這樣做可以使您的系統經得起錯誤的終止。使用 HttpSession 存儲和用戶相關的狀態。
以我們的觀點看來,有狀態會話 bean 的概念已經過時了。如果您仔細對其考慮一下,一個有 狀態會話 bean 實際上與一個 CORBA 對象在體系結構上是完全相同的,無非就是一個對象實例,綁定到一個服務器,并且依賴于服務器來管理 其生命周期。如果服務器關閉了,這種對象也就不存在,那么這個 bean 的客戶端的信息也就不存在。
J2EE 應用服務器為有狀態會 話 bean 提供的故障轉移(failover)能夠解決一些問題,但是有狀態的解決方案沒有無狀態的解決方案易于擴展。例如,在 WebSphere Application Server 中,對無狀態會話 bean 的請求,是通過對部署無狀態會話的成員集群進行平衡加載來實現。相反地,J2EE 應用服務器 不能對有狀態 bean 的請求進行平衡加載。這意味著您的集群中的服務器的加載過程會是不均衡的。此外,使用有狀態會話 bean 將會再添加 一些狀態到您的應用服務器上,這也是不好的做法。這樣就增加了系統的復雜性,并且在出現故障的情況下使問題變得復雜化。創建健壯的分 布式系統的一個關鍵原則是盡量使用無狀態行為。
因此,我們建議對大多數應用程序使用無狀態會話 bean 方法。任何在處理時需要 使用的與用戶相關的狀態應該以參數的形式傳送到 EJB 的方法中(并且通過使用一種機制如 HttpSession 來存儲它)或者從持久性的后端存 儲(例如通過使用實體 bean)作為 EJB 事務的一部分來進行檢索。在合適的情況下,這個信息可以緩存到內存中,但是要注意在分布式的環境 中保存這種緩存所潛在的挑戰性。緩存非常適合于只讀數據。
總之,您要確保從一開始就要考慮到可伸展性。檢查設計中的所有設想 ,并且考慮到當您的應用程序要在多個服務器上運行時,是否也可以正常運行。這個規則不但適合上述情況的應用程序代碼,也適用于如 MBean 和其他管理界面的情況下。
避免使用有狀態性不只是對 IBM/WebSphere 的建議,這是一個基本的 J2EE 設計原則。
8. 使用容器管理的事務
學習一下 J2EE 中的兩階段提交事務,并且使用這種方式,而不是開放您自己的 事務管理。容器在事務優化方面幾乎總是比較好的。
使用容器管理的事務(CMT)提供了兩個關鍵的優勢(如果沒有容器支持這幾乎 是不可能的):可組合的工作單元和健壯的事務行為。
如果您的應用程序代碼顯式地使用了開始和結束事務(也許使用 javax.jts.UserTransaction 或者甚至是本地資源事務),而將來的要求需要組合模塊(也許會是代碼重構的一部分),這種情況下往往需要 改變事務代碼。例如,如果模塊 A 開始了一個數據庫事務,更新數據庫,隨后提交事務,并且有模塊 B 做出同樣的處理,請考慮一下當您在 模塊 C 中嘗試使用上述兩個模塊,會出現什么情況呢?現在,模塊 C 正在執行一個邏輯動作,而這個動作實際上將調用兩個獨立的事務。如 果模塊 B 在執行中失敗了,而模塊 A 的事務仍然能被提交。這是我們所不希望出現的行為。如果,相反地,模塊 A 和模塊 B 都使用 CMT 的 話,模塊 C 也可以開始一個 CMT(通常通過配置描述符),并且在模塊 A 和模塊 B 中的事務將是同一個事務的隱含部分,這樣就不再需要復 雜的重寫代碼的工作了。
如果您的應用程序在同一個操作中需要訪問多種資源,您就要使用兩階段提交事務。例如,如果從 JMS 隊 列中刪除一個消息,并且隨后更新基于這條消息的紀錄,這時,要保證這兩個操作都會執行或都不會執行就變得尤為重要。如果一條消息已經 從隊列中被刪除,而系統沒有更新與此消息相關的數據庫中的紀錄,那么這種系統是不穩定的。一些嚴重的客戶及商業糾紛源自不一致的狀態 。
我們時??吹揭恍┛蛻魬贸绦蛟噲D實現他們自己的解決方案。也許會通過應用程序的代碼在數據庫更新失敗的時候 "撤銷"對隊 列的操作。我們不提倡這樣做。這種實現要比您最初的想象要復雜得多,并且還有許多其他的情況(想象一下如果應用程序在執行此操作的過 程中突然崩潰的情況)。作為替代的方式,應該使用兩階段提交事務。如果您使用 CMT,并且在一個單一的 CMT 中訪問兩階段提交的資源(例 如 JMS 和大多數數據庫),WebSphere 將會處理所有的復雜工作。它將確保整個事務被執行或者都不被執行,包括系統崩潰、數據庫崩潰或其 他的情況。其實現在事務日志中保存著事務狀態。當應用程序訪問多種資源的時候,我們怎么強調使用 CMT 事務的必要性都不為過。
只有在需要多種表示輸出類型,并且輸出類型被一個單一的控制器及后端支持時才使 用 XML/XSLT。
我們常聽到一些爭論說,為什么您選擇 XML/XSLT 而不是 JSP 作為表示層技術。選擇 XML/XSLT 的人的觀點是,JSP" 允許您將模型和視圖混合在一起",而 XML/XSLT 不會有這種問題。遺憾的是,這種觀點并不完全正確,或者至少不像白與黑那樣分的清楚。實 際上,XSL 和 XPath 是編程語言。XSL 是圖靈完成的(Turing-complete),盡管它不符合大多數人定義的編程語言,因為它是基于規則的, 并且不具備程序員習慣的控制工具。
現在的問題是既然給予了這種靈活性,開發人員就會利用這種靈活性。盡管每個人都認同 JSP 使開發人員容易在視圖中加入"類似模型"的行為,而實際上,在 XSL 中也有可能做出一些同樣的事情。盡管從 XSL 中進行訪問數據庫這樣的 事情會非常困難,但是我們曾經見到過一些異常復雜的 XSLT 樣式表執行復雜的轉換,這實際上是模型代碼。
然而,應該選擇 JSP 作為首選的表示技術的最基本的原因是,JSP 是現在支持最廣泛的、也是最被廣泛理解的 J2EE 視圖技術。而隨著自定義標記庫、JSTL 和 JSP2.0 的新特性的引入,創建 JSP 變得更加容易,并且不需要任何 Java 代碼,以及可以將模型和視圖清晰的分離開。在一些開發環境中( 如 WebSphere Studio)加入了對 JSP(包括對調試的支持)的強大支持,并且許多開發人員發現使用 JSP 進行開發要比使用 XLS 簡單,一些 支持 JSP 的圖形設計工具及其他特征(尤其在 JSF 這樣的框架下)使得開發人員可以以所見即所得的方式進行 JSP 的開發,而對于 XSL 有 時不容易做到。
最后一個要謹慎考慮使用 JSP 的原因是速度問題。在 IBM 所作的對比 XSL 和 JSP 相對速度的性能測試顯示:在大 多數情況下,JSP 在生成同樣的 HTML 的時候,要比 XSL 快好幾倍,甚至使用編譯過的 XSL 也是如此。盡管多數情況下這不是問題,但在性 能要求很高的情況下,這就會成為問題。
然而,這也不能說,您永遠也不要使用 XSL。在一些情況下,XSL 能夠表示一組固定的數據 ,并且可以基于不同的樣式表來以不同的方式顯示這些數據的能力是顯示視圖的最佳解決方案。然而,這只是一種例外的情況,而不是通用的 規則。如果您只是生成 HTML 來表達每一個頁面,那么在大多數情況下,XSL 是一種不必要的技術,并且,它給您的開發人員所帶來的問題遠 比它所能解決的問題多。
10. 當使用 HttpSession 時,盡量只將當前事務所需要的狀態保存其中,其他內容不要保存在 HttpSession 中。?
啟用會話持久性。
HttpSessions 對于存儲應用程序狀態信息是非常有用的。其 API 易于使用和理解。遺憾的是,開發人員常常遺忘了 HttpSession 的目的----用來保持暫時的用戶狀態。它不是任意的數據緩存。我們已經 見到過太多的系統為每個用戶的會話放入了大量的數據(達到兆字節)。那好了,如果同時有 1000 個登錄系統的用戶,每個用戶擁有 1MB 的 會話數據,那么就需要 1G 或者更多的內存用于這些會話。要使這些 HTTP 會話數據較小一些,不然的話,您的應用程序的性能將會下降。一 個大約比較合適的數據量應該是每個用戶的會話數據在 2K-4K 之間,這不是一個硬性的規則,8K 仍然沒有問題,但是顯然會比 2K 時的速度 要慢。一定要注意,不要使 HttpSession 變成數據堆積的場所。?
一個常見的問題是使用 HttpSession 緩存一些很容易再創建 的信息,如果有必要的話。由于會話是持久性的,進行不必要的序列化以及寫入數據是一種很奢侈的決定。相反地,應該使用內存中的哈希表 來緩存數據,并且在會話中保存一個對此數據進行引用的關鍵字。這樣,如果不能成功登錄到另外的應用服務器的話,就可以重新創建數據。
當談及會話持久性時,不要忘記要啟用這項功能。如果您沒有啟用會話持久性,或者服務器因為某種原因停止了(服務器故障或正常 的維護),則所有此應用服務的當前用戶的會話將會丟失。這是件令人非常不高興的事情。用戶不得不重新登錄,并且重新做一些他們曾經已 經做過的事情。相反地,如果啟用了會話持久性,WebSphere 會自動將用戶(以及他們的會話)移到另外一個應用服務器上去。用戶甚至不知 道會有這種事情的發生。我們曾經見到過一些產品系統因為存在于本地代碼中令人難以忍受的 bug(不是 IBM 的代碼?。┒蝗槐罎⒌那闆r, 這這種情況下,上述功能仍然可以運行良好。?
11. 在 WebSphere 中,使用動態緩存,并使用 WebSphere servlet 緩 存機制。?
通過使用這些功能,系統性能可以得到很大的提高,而開銷是很小的。并且不影響編程模型。
通 過緩存來提高性能的好處是眾所周知的事情。遺憾的是,當前的 J2EE 規范沒有包括一種用于 servlet/JSP 緩存的機制。然而,WebSphere 提 供了對頁面以及片斷緩存的支持,這種支持是通過其動態緩存功能來實現的,并且不需要對應用程序作出任何改變。其緩存的策略是聲明性的 ,而且其配置是通過 XML 配置描述符來實現的。因此,您的應用程序不會受到影響,并保持與 J2EE 規范的兼容性和移植性,同時還從 WebSphere 的 servlet 及 JSP 的緩存機制中得到性能的優化。
從 servet 及 JSP 的動態緩存機制得到的性能的提高是顯而易見的 ,這取決于應用程序的特性。Cox 和 Martin [Cox] 指出對一個現有的 RDF(資源描述格式)站點摘要 (RSS)servlet,當使用動態緩存時,其 性能可以提高 10%。請注意這個實驗只涉及到一個簡單的 servlet,這個性能的增長量可能并不能反映一個復雜的應用程序。
為了更 多地提高性能,將 WebSphere servlet/JSP 結果緩存與 WebSphere 插件 ESI Fragment 處理器、IBM HTTP Server Fast Response Cache Accelerator (FRCA) 和 Edge Server 緩存功能集成在一起。對于繁重的基于讀取的工作負荷,通過使用這些功能可以得到許多額外的好處。
12. 為了提高程序員的工作效率,將 CMP 實體 bean 作為 O/R 映射的首選解決方案.
通過 WebSphere 框架(readahead、緩存、隔離級別等)優化性能。如果可能,有選擇的應用一些模式來達到提高性能的目的,例如 Fast-Lane 閱讀器 [Marinescu]。
對象/關系(O/R)映射是使用 Java 創建企業級的應用程序的基礎。幾乎每個 J2EE 應用程序都需要一些類型的 O/R 映射。J2EE 廠商提供一種 O/R 映射機制,這種機制在不同的廠商間是可移植的,高效的,并且能夠被一些標準及工具很好地支持。這就是 EJB 規范中的 CMP(容器管理的持久性)部分。
早期的 CMP 實現以表現不佳及不支持許多 SQL 結構而著稱。然而,隨著 EJB 2.0 及 2.1 規范的出現,以及被一些廠商所采納,并且隨著像 IBM WebSphere Studio Application Developer 的出現,這些問題已經不再是問題 了。
CMP EJB 組件現在已經被廣泛地應用于許多高性能的應用程序中。WebSphere 包括一些優化功能以提高 EJB 組件的性能,優化 功能包括:對生命周期的緩存和 read-ahead 能力。這兩者優化功能都是配置時的選項,并且不需要對應用程序進行修改或者影響可移植性。
處于緩存狀態的生命周期緩存 CMP 狀態數據并提供基于時間的無效性。從處于緩存狀態的生命周期得到的性能提高可以達到選項 A 的緩存性能,并且仍然可以為您的應用程序提供可伸展性。Read-ahead 能力和容器管理的關系結合使用。這個特性通過在相同的查詢中隨意地 檢索相關的數據作為父數據而減少與數據庫的交互。如果相關的數據要通過使用并發的查詢來訪問的話,這種方法可以得到性能的改進。 [Gunther]提供了詳細的描述以及通過這些特性得到的性能提高的細節。
此外,為了完全優化您的 EJB 組件,當指定隔離級別時要特 別注意。盡可能使用最低的隔離級別,并且仍然保持您的數據的完整性。較低的隔離級別可以提供最佳的性能,并且可以降低出現數據庫死鎖 的危險。
這是目前最有爭議的最佳實踐。已經有大量的文章贊揚 CMP EJB,同樣的貶斥聲也不絕于耳。然而,這里最基本的問題是數 據庫開發是困難的。當您開始使用任何持久性解決方案之前,您需要掌握查詢以及數據庫鎖定如何工作這些基礎知識。如果您選擇使用 CMP EJB,您要確保您已經通過一些書籍(例如 [Brown] 和 [Barcia])知道如何使用它們。在鎖定及爭用方面有一些微妙的交互難以理解,但是, 在您耗費一定的時間及努力后會將其掌握的