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

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

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

    我的Blog我做主^_^

    走向一條通往JAVA的不歸路...

      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      64 隨筆 :: 68 文章 :: 77 評論 :: 0 Trackbacks

    簡介
    在過去的 5 年中,已經(jīng)有許多人寫了關于 J2EE 最佳實踐方面的書以及文章。現(xiàn)在大約有 10 本(或更多的)書以及眾多的文章,它們對如何構建 J2EE 應用程序提出了深刻的見解。實際上,這方面的參考資料如此之多,并且這些參考資料之間往往還存在著一些矛盾的推薦,當您經(jīng)歷這些迷惑的時候,這些迷惑會對使用 J2EE 本身形成一種阻礙。為了能夠為存有此迷惑的人提供一些簡單的指導,于是我們列出了下面的%26#8220;最重要的 10 個%26#8221;清單,它們是我們感覺最重要的 J2EE 最佳實踐。遺憾的是,10 項內(nèi)容不足以闡述所有的內(nèi)容,尤其是當您將 Web 服務開發(fā)作為 J2EE 的一部分。因此,為了使 J2EE 得到發(fā)展,我們決定使用%26#8220;最重要的 12 個%26#8221;清單而不是%26#8220;最重要的 10 個%26#8221;清單。

    為了不使問題復雜化,我們就使用%26#8212;%26#8212;最重要的 10 (+ 2) J2EE 最佳實踐%26#8230;%26#8230;

    最佳實踐

    1. 始終使用 MVC 框架。
    2. 在每一層都應用自動單元測試和測試管理。
    3. 按照規(guī)范來進行開發(fā),而不是按照應用服務器來進行開發(fā)。
    4. 從一開始就計劃使用 J2EE 安全性。
    5. 創(chuàng)建您所知道的。
    6. 當使用 EJB 組件時,始終使用會話 Facades。
    7. 使用無狀態(tài)會話 bean,而不是有狀態(tài)會話 bean.
    8. 使用容器管理的事務。
    9. 將 JSP 作為表示層的首選。
    10. 當使用 HttpSession 時,盡量只將當前事務所需要的狀態(tài)保存其中,其他內(nèi)容不要保存在 HttpSession 中。
    11. 在 WebSphere 中,啟動動態(tài)緩存,并使用 WebSphere servlet 緩存機制。
    12. 為了提高程序員的工作效率,將 CMP 實體 bean 作為 O/R 映射的首選解決方案。

    1. 始終使用 MVC 框架。

    MVC 框架可以將業(yè)務邏輯(Java beans 和 EJB 組件)、控制器邏輯(Servlets/Struts 動作)、表示層(JSP、XML/XSLT)清晰地分離開來。良好的分層可以帶來許多好處。

    MVC 框架對于成功使用 J2EE 是如此重要,以致沒有其他最佳實踐可以與其相提并論。模型-視圖-控制器(MVC)是設計 J2EE 應用程序的基礎。MVC 將您的程序代碼簡單地劃分下面幾個部分:

    1. 負責業(yè)務邏輯的代碼(即模型%26#8212;%26#8212;通常使用 EJB 或者普通的 Java 對象來實現(xiàn))。
    2. 負責用戶界面顯示的代碼(即視圖%26#8212;%26#8212;通常通過 JSP 及標記庫來實現(xiàn),有時也使用 XML 和 XSLT 來實現(xiàn))。
    3. 負責應用程序流程的代碼(即控制器%26#8212;%26#8212;通常使用 Java Servlet 或像 Struts 控制器這樣的類來實現(xiàn))。

    現(xiàn)在有許多關于 MVC 的極好的綜述,我們特別推薦感興趣的讀者可以參考 [Fowler] 或 [Brown] 的文章(請參見參考資料),您可以從中得到對 MVC 全面而深刻的理解。

    如果您不遵循基本的 MVC 框架,在開發(fā)過程中就會出現(xiàn)許多的問題。最常見的問題就是在視圖部分添加了太多的成分,例如,可能存在使用 JSP 標記來執(zhí)行數(shù)據(jù)庫訪問,或者在 JSP 中進行應用程序的流程控制,這在小規(guī)模的應用程序中是比較常見的,但是,隨著后期的開發(fā),這樣做將會帶來問題,因為 JSP 逐步變得越來越難以維護和調(diào)試。

    類似地,我們也經(jīng)常看到將視圖層構建到業(yè)務邏輯的情況。例如,一個常見的問題就是將在構建視圖時使用的 XML 解析技術直接應用到業(yè)務層。業(yè)務層應該對業(yè)務對象%26#8212;%26#8212;而不是綁定到視圖的特定數(shù)據(jù)表示進行操作。

    然而,只是具有合適的組件并不一定意味著可以使您的應用程序得到合適的分層。我們常常見到一些應用程序包含 servlet、JSP 和 EJB 組件所有這三項,然而,其主要的業(yè)務邏輯卻是在 servlet 層實現(xiàn)的,或者應用程序導航是在 JSP 中處理的。您必須進行嚴格的代碼檢查并重構您的代碼,以確保應用程序的業(yè)務邏輯只在模型層(Model layer)進行處理,應用程序導航只通過控制器層(Controller layer)進行處理,而您的視圖(Views)只是將傳遞過來的模型對象以 HTML 及 JavaScript 的形式表示出來。

    2. 在應用程序的每一層都使用自動單元測試和測試管理。

    不要只是測試您的圖形用戶界面(GUI)。分層的測試使測試及維護工作變得極其簡單。

    在過去的幾年中,在方法學領域有了相當大的革新,例如新出現(xiàn)的被稱為 Agile(例如 SCRUM [Schwaber] 和極限編程 [Beck1],請參見參考資料)的輕量級方法現(xiàn)在已經(jīng)得到了很普遍的應用。幾乎所有的這些方法中的一個共同的特征是它們都提倡使用自動的測試工具,這些工具可以幫助開發(fā)人員用更少的時間進行回歸測試 (regression testing),并可以幫助他們避免由于不充分的回歸測試造成的錯誤,因此可以用來提高程序員的工作效率。實際上,還有一種被稱為 Test-First Development [Beck2] 的方法,這種方法甚至提倡在開發(fā)實際的代碼之前就先編寫單元測試。然而,在您測試代碼之前,您需要將代碼分割成一些可測試的片斷。一個%26#8220;大泥球%26#8221;是難以測試的,因為它不是只實現(xiàn)一個簡單的易于識別的功能。如果您的每個代碼片斷實現(xiàn)多個方面的功能,這樣的代碼將難以保證其完全的正確性。

    MVC 框架(以及 J2EE 中的 MVC 實現(xiàn))的一個優(yōu)點就是元素的組件化能夠(實際上,相當?shù)暮唵危δ膽贸绦蜻M行單元測試。因此,您可以方便地對實體 bean、會話 bean 以及 JSP 獨立編寫測試用例,而不必考慮其他的代碼。現(xiàn)在有許多用于 J2EE 測試的框架和工具,這些框架及工具使得這一過程更加簡單。例如,JUnit(是一種由 junit.org 開發(fā)的開放源代碼工具)和 Cactus(由 Apache 開發(fā)的開放源代碼工具)對于測試 J2EE 組件都非常有用。[Hightower] 詳細探討了如何在 J2EE 中使用這些工具。

    盡管所有這些詳述了怎樣徹底地測試您的應用程序,但是我們?nèi)匀豢吹揭恍┤苏J為只要他們測試了 GUI(可能是基于 Web 的 GUI,或者是獨立的 Java 應用程序),則他們就全面地測試了整個應用程序。GUI 測試很難達到全面的測試,有以下幾種原因。首先,使用 GUI 測試很難徹底地測試到系統(tǒng)的每一條路徑,GUI 僅僅是影響系統(tǒng)的一種方式,可能存在后臺運算、腳本和各種各樣的其他訪問點,這也需要進行測試。然而,它們通常并不具有 GUI。第二,GUI 級的測試是一種非常粗粒度的測試。這種測試只是在宏觀水平上測試系統(tǒng)的行為。這意味著一旦發(fā)現(xiàn)存在問題,則與此問題相關的整個子系統(tǒng)都要進行檢查,這使得找出 bug(缺陷)將是非常困難的事情。第三,GUI 測試通常只有在整個開發(fā)周期的后期才能很好地得到測試,這是因為只有這那個時候 GUI 才得到完整的定義。這意味著只有在后期才可能發(fā)現(xiàn)潛在的 bug。第四,一般的開發(fā)人員可能沒有自動的 GUI 測試工具。因此,當一個開發(fā)人員對代碼進行更改時,沒有一種簡單的方法來重新測試受到影響的子系統(tǒng)。這實際上不利于進行良好的測試。如果開發(fā)人員具有自動的代碼級單元測試工具,開發(fā)人員就能夠很容易地運行這些工具以確保所做的更改不會破壞已經(jīng)存在的功能。最后,如果添加了自動構建功能,則在自動構建過程中添加一個自動的單元測試工具是非常容易的事情。當完成這些設置以后,整個系統(tǒng)就可以有規(guī)律地進行重建,并且回歸測試幾乎不需要人的參與。

    另外,我們必須強調(diào),使用 EJB 和 Web 服務進行分布式的、基于組件的開發(fā)使得測試單個的組件變得非常必要。如果沒有%26#8220;GUI%26#8221;需要測試,您就必須進行低級(lower-level)測試。最好以這種方式開始測試,省得當您將分布式的組件或 Web 服務作為您的應用程序的一部分時,您不得不花費心思重新進行測試。

    總之,通過使用自動的單元測試,能夠很快地發(fā)現(xiàn)系統(tǒng)的缺陷,并且也易于發(fā)現(xiàn)這些缺陷,使得測試工作變得更加系統(tǒng)化,因此整體的質量也得以提高。

    3. 按照規(guī)范來進行開發(fā),而不是按照應用服務器來進行開發(fā)。

    要將規(guī)范熟記于心,如果要背離規(guī)范,要經(jīng)過慎密的考慮后才可以這樣做。這是因為當您背離規(guī)則的時候,您所做的事情往往并不是您應該做的事情。

    當您要背離 J2EE 可以允許您做的事情的時候,這很容易讓使您遭受不幸。我們發(fā)現(xiàn)有一些開發(fā)人員鉆研一些 J2EE 允許之外的東西,他們認為這樣做可以%26#8220;稍微%26#8221;改善J2EE的性能,而他們最終只會發(fā)現(xiàn)這樣做會引起嚴重的性能問題,或者在以后的移植(從一個廠商到另一個廠商,或者是更常見的從一個版本到另一個版本)中會出現(xiàn)問題。實際上,這種移植問題是如此嚴重,以致 [Beaton] 將此原則稱為移植工作的基本最佳實踐。

    現(xiàn)在有好幾個地方如果不直接使用 J2EE 提供的方法肯定會產(chǎn)生問題。一個常見的例子就是開發(fā)人員通過使用 JAAS 模塊來替代 J2EE 安全性,而不是使用內(nèi)置的遵循規(guī)范的應用程序服務器機制來進行驗證和授權。要注意不要脫離 J2EE 規(guī)范提供的驗證機制,如果脫離了此規(guī)范,這將是系統(tǒng)存在安全漏洞以及廠商兼容性問題的主要原因。類似地,要使用 servlet 和 EJB 規(guī)范提供的授權機制,并且如果您要偏離這些規(guī)范的話,要確保使用規(guī)范定義的 API(例如 getCallerPrincipal())作為實現(xiàn)的基礎。通過這種方式,您將能夠利用廠商提供的強安全性基礎設施,其中,業(yè)務要求需要支持復雜的授權規(guī)則。

    其他常見的問題包括使用不遵循 J2EE 規(guī)范的持久性機制(這使得事務管理變得困難)、在J2EE程序中使用不適當?shù)腏2SE 方法(例如線程或 singleton),以及使用您自己的方法解決程序到程序(program-to-program)的通信,而不是使用 J2EE 內(nèi)在支持的機制(例如 JCA、JMS 或 Web 服務)。當您將一個遵循 J2EE 的服務器移植到其他的服務器上,或者移植到相同服務器的新版本上,上述的設計選擇將會造成無數(shù)的問題。唯一要背離規(guī)范的情況是,當一個問題在規(guī)范的范圍內(nèi)無法解決的時候。例如,安排執(zhí)行定時的業(yè)務邏輯在 EJB2.1 出現(xiàn)之前是一個問題,在類似這樣的情況下,我們建議當有廠商提供的解決方案時就使用廠商提供的解決方案(例如 WebSphere Application Server Enterprise 中的 Scheduler 工具),而在沒有廠商提供的解決方案時就使用第三方提供的工具。如果使用廠商提供的解決方案,應用程序的維護以及將其移植到新的規(guī)范版本將是廠商的問題,而不是您的問題。

    最后,要注意不要太早地采用新技術。太過于熱衷采用還沒有集成到 J2EE 規(guī)范的其他部分或者還沒有集成到廠商的產(chǎn)品中的技術常會帶來災難性的后果。支持是關鍵的%26#8212;%26#8212;如果您的廠商不直接支持一種特定的在 JSR 中提出的技術,但此技術還沒有被 J2EE 所接受,那么您就不應該采用此技術。畢竟,我們中的大多數(shù)人從事解決業(yè)務問題,而不是推進技術的發(fā)展。

    4. 從一開始就計劃使用 J2EE 安全性。

    啟用 WebSphere 安全性。這使您的 EJB 和 URL 至少可以讓所有授權用戶訪問。不要問為什么%26#8212;%26#8212;照著做就是了。

    在與我們合作的客戶中,一開始就打算啟用 WebSphere J2EE 安全性的顧客是非常少的,這一點一直讓我們感到吃驚。據(jù)我們估計大約只有 50% 的顧客一開始就打算使用此特性。例如,我們曾與一些大型的金融機構(銀行、代理等等)合作過,他們也沒有打算啟用安全性。幸運的是,這種問題在部署之前的檢查時就得以解決.

    不使用 J2EE 安全性是危險的事情。假設您的應用程序需要安全性(幾乎所有的應用程序都需要),您敢打賭您的開發(fā)人員能夠構建出自己的安全性系統(tǒng),而這個系統(tǒng)比您從 J2EE 廠商那里買來的更好。這可不是個好的賭注,為分布式的應用程序提供安全性是異常困難的。例如,您需要使用網(wǎng)絡安全加密令牌控制對 EJB 的訪問。以我們的經(jīng)驗看來,大多數(shù)自己構建的安全性系統(tǒng)是不安全的,并且有重大的缺陷,這使產(chǎn)品系統(tǒng)極其脆弱(請參考 [Barcia] 第 18 章)。

    一些不使用 J2EE 安全性的理由包括:擔心性能的下降,相信其他的安全性(例如 Netegrity SiteMinder)可以取代 J2EE 安全性,或者是不知道 WebSphere Application Server 安全特性及功能。不要陷入這些陷阱之中,尤其是,盡管像 Netegrity SiteMinder 這樣的產(chǎn)品能夠提供優(yōu)秀的安全特性,但是僅僅其自身不可能保護整個 J2EE 應用程序。這些產(chǎn)品必須與 J2EE 應用程序服務器聯(lián)合起來才可能全面地保護您的系統(tǒng)。

    其他的一種常見的不使用 J2EE 安全性的原因是:基于角色的模型沒有提供足夠的粒度訪問控制以滿足復雜的業(yè)務規(guī)則。盡管事實是這樣的,但這也不應該成為不使用 J2EE 安全性的理由。相反地,應該將 J2EE 驗證及 J2EE 角色與特定的擴展規(guī)則結合起來。如果復雜的業(yè)務規(guī)則需要做出安全性決策,那就編寫相應的代碼,其安全性決策要基于可以直接使用的以及可靠的 J2EE 驗證信息(用戶 ID 和角色)。

    5. 創(chuàng)建您所知道的。

    反復的開發(fā)工作將使您能夠逐漸地掌握所有的 J2EE 模塊。要從創(chuàng)建小而簡單的模塊開始而不是從一開始就馬上涉及到所有的模塊。

    我們必須承認 J2EE 是龐大的體系。如果一個開發(fā)小組只是開始使用 J2EE,這將很難一下子就能掌握它。在 J2EE 中有太多的概念和 API 需要掌握。在這種情況下,成功掌握 J2EE 的關鍵是從簡單的步驟開始做起。

    這種方法可以通過在您的應用程序中創(chuàng)建小而簡單的模塊來得到最好的實現(xiàn)。如果一個開發(fā)小組通過創(chuàng)建一個簡單的域模型以及后端的持久性機制(也許使用的是 JDBC),并且對其進行了完整的測試,這會增強他們的自信心,于是他們會使用該域模型去掌握使用 servlet 和 JSP 的前端開發(fā)。如果一個開發(fā)組發(fā)現(xiàn)有必要使用 EJB,他們也會類似地開始在容器管理的持久性 EJB 組件之上使用簡單的會話 Facades,或者使用基于 JDBC 的數(shù)據(jù)訪問對象(JDBC-based Data Access Objects,DAO),而不是跳過這些去使用更加復雜的構造(例如消息驅動bean和JMS)。

    這種方法并不是什么新方法,但是很少有開發(fā)組以這種方式來培養(yǎng)他們的技能。相反地,多數(shù)開發(fā)組由于嘗試馬上就構建所有的模塊,同時涉及 MVC 中的視圖層、模型層和控制器層,這樣做的結果是他們往往會陷入進度的壓力之中。他們應該考慮一些敏捷(Agile)開發(fā)方法,例如極限編程(XP),這種開發(fā)方法采用一種增量學習及開發(fā)方法。在 XP 中有一種稱為 ModelFirst [Wiki] 的過程,這個過程涉及到首先構建域模型作為一種機制來組織和實現(xiàn)用戶場景。基本說來,您要構建域模型作為您要實現(xiàn)的用戶場景的首要部分,然后在域模型之上構建一個用戶界面(UI)作為用戶場景實現(xiàn)的結果。這種方法非常適合讓一個開發(fā)組一次只學到一種技術,而不是讓他們同時面對很多種情況(或者讓他們讀很多書),這會令他們崩潰的。

    還有,對每個應用程序層重復的開發(fā)可能會包含一些適當?shù)哪J郊白罴褜嵺`。如果您從應用程序的底層開始應用一些模式如數(shù)據(jù)訪問對象和會話 Facades,您就不應該在您的JSP和其他視圖對象中使用域邏輯。

    最后,當您開發(fā)一些簡單的模塊時,在開始的初期就可以對您的應用程序進行性能測試。如果直到應用程序開發(fā)的后期才進行性能測試的話,這往往會出現(xiàn)災難性的后果,正如 [Joines] 所述。

    6. 當使用 EJB 組件時,始終使用會話 Facades。

    決不要將實體 bean 直接暴露給任何用戶類型。對實體 bean 只可以使用本地 EJB 接口(Local EJB interfaces)。

    當使用 EJB 組件時,使用一個會話 Facades 是一個確認無疑的最佳實踐。實際上,這個通用的實踐被廣泛地應用到任何分布式的技術中,包括 CORBA、EJB 和 DCOM。從根本上講,您的應用程序的分布%26#8220;交叉區(qū)域%26#8221;越是底層化,對小塊的數(shù)據(jù)由于多次重復的網(wǎng)絡中繼造成的時間消耗就越少。要達到這個目的的方法就是:創(chuàng)建大粒度的 Facades 對象,這個對象包含邏輯子系統(tǒng),因而可以通過一個方法調(diào)用就可以完成一些有用的業(yè)務功能。這種方法不但能夠降低網(wǎng)絡開銷,而且在 EJB 內(nèi)部通過為整個業(yè)務功能創(chuàng)建一個事務環(huán)境也可以大大地減少對數(shù)據(jù)庫的訪問次數(shù)([Brown] 對其進行了詳細的討論。[Alur] 對這種模式進行了規(guī)范的表示。[Fowler](并且包括除 EJB 之外的情況)和 [Marinescu] 也對其進行了描述。請參見參考資料)。

    EJB 本地接口(從 EJB 2.0 規(guī)范開始使用)為共存的 EJB 提供了性能優(yōu)化方法。本地接口必須被您的應用程序顯式地進行訪問,這需要代碼的改變和防止以后配置 EJB 時需要應用程序的改變。由于會話 Facades 和它包含的整個 EJB 對于彼此來說都應該是本地的,我們建議對會話 Facades 后面的實體 bean 使用本地接口。然而,會話 Facades 本身的實現(xiàn)(典型例子如無狀態(tài)會話 bean)應該設計為遠程接口。

    為了性能的優(yōu)化,可以將一個本地接口添加到會話 Facades。這樣做利用了這樣一個事實:在大多數(shù)情況下(至少在 Web 應用程序中),您的 EJB 客戶端和 EJB 會共同存在于同一個 Java 虛擬機(JVM)中。另外一種情況,如果會話 Facades 在本地被調(diào)用,可以使用 J2EE 應用服務器配置優(yōu)化(configuration optimizations),例如 WebSphere 中的%26#8220;No Local Copies%26#8221;。然而,您必須注意到這些可供選擇的方案會將交互方法從按值傳遞(pass-by-value)改變?yōu)榘匆脗鬟f(pass-by-reference)。這可能會在您的代碼中產(chǎn)生很微妙的錯誤。當您要利用這些方案時,您應該在一開始就考慮其可行性。

    如果在您的會話 Facades 中使用遠程接口(而不是本地接口),您也可以將同樣的會話 Facades 在 J2EE 1.4 中以兼容的方式作為 Web 服務來配置。這是因為 JSR 109(J2EE 1.4 中的 Web 服務部署部分)要求使用無狀態(tài)會話 bean 的遠程接口作為 EJB Web 服務和 EJB 實現(xiàn)的接口。這樣做是值得的,因為這樣做可以為您的業(yè)務邏輯增加客戶端類型的數(shù)量。

    7. 使用無狀態(tài)會話 bean,而不是有狀態(tài)會話 bean。

    這樣做可以使您的系統(tǒng)經(jīng)得起錯誤的終止。使用 HttpSession 存儲和用戶相關的狀態(tài)。

    以我們的觀點看來,有狀態(tài)會話 bean 的概念已經(jīng)過時了。如果您仔細對其考慮一下,一個有狀態(tài)會話 bean 實際上與一個 CORBA 對象在體系結構上是完全相同的,無非就是一個對象實例,綁定到一個服務器,并且依賴于服務器來管理其生命周期。如果服務器關閉了,這種對象也就不存在,那么這個 bean 的客戶端的信息也就不存在。

    J2EE 應用服務器為有狀態(tài)會話 bean 提供的故障轉移(failover)能夠解決一些問題,但是有狀態(tài)的解決方案沒有無狀態(tài)的解決方案易于擴展。例如,在 WebSphere Application Server 中,對無狀態(tài)會話 bean 的請求,是通過對部署無狀態(tài)會話的成員集群進行平衡加載來實現(xiàn)。相反地,J2EE 應用服務器不能對有狀態(tài) bean 的請求進行平衡加載。這意味著您的集群中的服務器的加載過程會是不均衡的。此外,使用有狀態(tài)會話 bean 將會再添加一些狀態(tài)到您的應用服務器上,這也是不好的做法。這樣就增加了系統(tǒng)的復雜性,并且在出現(xiàn)故障的情況下使問題變得復雜化。創(chuàng)建健壯的分布式系統(tǒng)的一個關鍵原則是盡量使用無狀態(tài)行為。

    因此,我們建議對大多數(shù)應用程序使用無狀態(tài)會話 bean 方法。任何在處理時需要使用的與用戶相關的狀態(tài)應該以參數(shù)的形式傳送到 EJB 的方法中(并且通過使用一種機制如 HttpSession 來存儲它)或者從持久性的后端存儲(例如通過使用實體 bean)作為 EJB 事務的一部分來進行檢索。在合適的情況下,這個信息可以緩存到內(nèi)存中,但是要注意在分布式的環(huán)境中保存這種緩存所潛在的挑戰(zhàn)性。緩存非常適合于只讀數(shù)據(jù)。

    總之,您要確保從一開始就要考慮到可伸展性。檢查設計中的所有設想,并且考慮到當您的應用程序要在多個服務器上運行時,是否也可以正常運行。這個規(guī)則不但適合上述情況的應用程序代碼,也適用于如 MBean 和其他管理界面的情況下。

    避免使用有狀態(tài)性不只是對 IBM/WebSphere 的建議,這是一個基本的 J2EE 設計原則。請參見 [Jewell] 的 Tyler Jewell 對有狀態(tài) bean 的批評,其觀點和上述的觀點是相同的。

    8. 使用容器管理的事務。

    學習一下 J2EE 中的兩階段提交事務,并且使用這種方式,而不是開放您自己的事務管理。容器在事務優(yōu)化方面幾乎總是比較好的。

    使用容器管理的事務(CMT)提供了兩個關鍵的優(yōu)勢(如果沒有容器支持這幾乎是不可能的):可組合的工作單元和健壯的事務行為。

    如果您的應用程序代碼顯式地使用了開始和結束事務(也許使用 javax.jts.UserTransaction 或者甚至是本地資源事務),而將來的要求需要組合模塊(也許會是代碼重構的一部分),這種情況下往往需要改變事務代碼。例如,如果模塊 A 開始了一個數(shù)據(jù)庫事務,更新數(shù)據(jù)庫,隨后提交事務,并且有模塊 B 做出同樣的處理,請考慮一下當您在模塊 C 中嘗試使用上述兩個模塊,會出現(xiàn)什么情況呢?現(xiàn)在,模塊 C 正在執(zhí)行一個邏輯動作,而這個動作實際上將調(diào)用兩個獨立的事務。如果模塊 B 在執(zhí)行中失敗了,而模塊 A 的事務仍然能被提交。這是我們所不希望出現(xiàn)的行為。如果,相反地,模塊 A 和模塊 B 都使用 CMT 的話,模塊 C 也可以開始一個 CMT(通常通過配置描述符),并且在模塊 A 和模塊 B 中的事務將是同一個事務的隱含部分,這樣就不再需要復雜的重寫代碼的工作了。

    如果您的應用程序在同一個操作中需要訪問多種資源,您就要使用兩階段提交事務。例如,如果從 JMS 隊列中刪除一個消息,并且隨后更新基于這條消息的紀錄,這時,要保證這兩個操作都會執(zhí)行或都不會執(zhí)行就變得尤為重要。如果一條消息已經(jīng)從隊列中被刪除,而系統(tǒng)沒有更新與此消息相關的數(shù)據(jù)庫中的紀錄,那么這種系統(tǒng)是不穩(wěn)定的。一些嚴重的客戶及商業(yè)糾紛源自不一致的狀態(tài)。

    我們時常看到一些客戶應用程序試圖實現(xiàn)他們自己的解決方案。也許會通過應用程序的代碼在數(shù)據(jù)庫更新失敗的時候 %26#8220;撤銷%26#8221;對隊列的操作。我們不提倡這樣做。這種實現(xiàn)要比您最初的想象要復雜得多,并且還有許多其他的情況(想象一下如果應用程序在執(zhí)行此操作的過程中突然崩潰的情況)。作為替代的方式,應該使用兩階段提交事務。如果您使用 CMT,并且在一個單一的 CMT 中訪問兩階段提交的資源(例如 JMS 和大多數(shù)數(shù)據(jù)庫),WebSphere 將會處理所有的復雜工作。它將確保整個事務被執(zhí)行或者都不被執(zhí)行,包括系統(tǒng)崩潰、數(shù)據(jù)庫崩潰或其他的情況。其實現(xiàn)在事務日志中保存著事務狀態(tài)。當應用程序訪問多種資源的時候,我們怎么強調(diào)使用 CMT 事務的必要性都不為過。

    9. 將 JSP 作為表示層的首選。

    只有在需要多種表示輸出類型,并且輸出類型被一個單一的控制器及后端支持時才使用 XML/XSLT。

    我們常聽到一些爭論說,為什么您選擇 XML/XSLT 而不是 JSP 作為表示層技術。選擇 XML/XSLT 的人的觀點是,JSP%26#8220; 允許您將模型和視圖混合在一起%26#8221;,而 XML/XSLT 不會有這種問題。遺憾的是,這種觀點并不完全正確,或者至少不像白與黑那樣分的清楚。實際上,XSL 和 XPath 是編程語言。XSL 是圖靈完成的(Turing-complete),盡管它不符合大多數(shù)人定義的編程語言,因為它是基于規(guī)則的,并且不具備程序員習慣的控制工具。

    現(xiàn)在的問題是既然給予了這種靈活性,開發(fā)人員就會利用這種靈活性。盡管每個人都認同 JSP 使開發(fā)人員容易在視圖中加入%26#8220;類似模型%26#8221;的行為,而實際上,在 XSL 中也有可能做出一些同樣的事情。盡管從 XSL 中進行訪問數(shù)據(jù)庫這樣的事情會非常困難,但是我們曾經(jīng)見到過一些異常復雜的 XSLT 樣式表執(zhí)行復雜的轉換,這實際上是模型代碼。

    然而,應該選擇 JSP 作為首選的表示技術的最基本的原因是,JSP 是現(xiàn)在支持最廣泛的、也是最被廣泛理解的 J2EE 視圖技術。而隨著自定義標記庫、JSTL 和 JSP2.0 的新特性的引入,創(chuàng)建 JSP 變得更加容易,并且不需要任何 Java 代碼,以及可以將模型和視圖清晰的分離開。在一些開發(fā)環(huán)境中(如 WebSphere Studio)加入了對 JSP(包括對調(diào)試的支持)的強大支持,并且許多開發(fā)人員發(fā)現(xiàn)使用 JSP 進行開發(fā)要比使用 XLS 簡單,一些支持 JSP 的圖形設計工具及其他特征(尤其在 JSF 這樣的框架下)使得開發(fā)人員可以以所見即所得的方式進行 JSP 的開發(fā),而對于 XSL 有時不容易做到。

    最后一個要謹慎考慮使用 JSP 的原因是速度問題。在 IBM 所作的對比 XSL 和 JSP 相對速度的性能測試顯示:在大多數(shù)情況下,JSP 在生成同樣的 HTML 的時候,要比 XSL 快好幾倍,甚至使用編譯過的 XSL 也是如此。盡管多數(shù)情況下這不是問題,但在性能要求很高的情況下,這就會成為問題。

    然而,這也不能說,您永遠也不要使用 XSL。在一些情況下,XSL 能夠表示一組固定的數(shù)據(jù),并且可以基于不同的樣式表(請參見 [Fowler])來以不同的方式顯示這些數(shù)據(jù)的能力是顯示視圖的最佳解決方案。然而,這只是一種例外的情況,而不是通用的規(guī)則。如果您只是生成 HTML 來表達每一個頁面,那么在大多數(shù)情況下,XSL 是一種不必要的技術,并且,它給您的開發(fā)人員所帶來的問題遠比它所能解決的問題多。

    10. 當使用 HttpSession 時,盡量只將當前事務所需要的狀態(tài)保存其中,其他內(nèi)容不要保存在 HttpSession 中。

    啟用會話持久性。

    HttpSessions 對于存儲應用程序狀態(tài)信息是非常有用的。其 API 易于使用和理解。遺憾的是,開發(fā)人員常常遺忘了 HttpSession 的目的%26#8212;%26#8212;用來保持暫時的用戶狀態(tài)。它不是任意的數(shù)據(jù)緩存。我們已經(jīng)見到過太多的系統(tǒng)為每個用戶的會話放入了大量的數(shù)據(jù)(達到兆字節(jié))。那好了,如果同時有 1000 個登錄系統(tǒng)的用戶,每個用戶擁有 1MB 的會話數(shù)據(jù),那么就需要 1G 或者更多的內(nèi)存用于這些會話。要使這些 HTTP 會話數(shù)據(jù)較小一些,不然的話,您的應用程序的性能將會下降。一個大約比較合適的數(shù)據(jù)量應該是每個用戶的會話數(shù)據(jù)在 2K-4K 之間,這不是一個硬性的規(guī)則,8K 仍然沒有問題,但是顯然會比 2K 時的速度要慢。一定要注意,不要使 HttpSession 變成數(shù)據(jù)堆積的場所。

    一個常見的問題是使用 HttpSession 緩存一些很容易再創(chuàng)建的信息,如果有必要的話。由于會話是持久性的,進行不必要的序列化以及寫入數(shù)據(jù)是一種很奢侈的決定。相反地,應該使用內(nèi)存中的哈希表來緩存數(shù)據(jù),并且在會話中保存一個對此數(shù)據(jù)進行引用的關鍵字。這樣,如果不能成功登錄到另外的應用服務器的話,就可以重新創(chuàng)建數(shù)據(jù)。(請參見 [Brown2])

    當談及會話持久性時,不要忘記要啟用這項功能。如果您沒有啟用會話持久性,或者服務器因為某種原因停止了(服務器故障或正常的維護),則所有此應用服務的當前用戶的會話將會丟失。這是件令人非常不高興的事情。用戶不得不重新登錄,并且重新做一些他們曾經(jīng)已經(jīng)做過的事情。相反地,如果啟用了會話持久性,WebSphere 會自動將用戶(以及他們的會話)移到另外一個應用服務器上去。用戶甚至不知道會有這種事情的發(fā)生。我們曾經(jīng)見到過一些產(chǎn)品系統(tǒng)因為存在于本地代碼中令人難以忍受的 bug(不是 IBM 的代碼!)而突然崩潰的情況,這這種情況下,上述功能仍然可以運行良好。

    11. 在 WebSphere 中,使用動態(tài)緩存,并使用 WebSphere servlet 緩存機制.

    通過使用這些功能,系統(tǒng)性能可以得到很大的提高,而開銷是很小的。并且不影響編程模型。

    通過緩存來提高性能的好處是眾所周知的事情。遺憾的是,當前的 J2EE 規(guī)范沒有包括一種用于 servlet/JSP 緩存的機制。然而,WebSphere 提供了對頁面以及片斷緩存的支持,這種支持是通過其動態(tài)緩存功能來實現(xiàn)的,并且不需要對應用程序作出任何改變。其緩存的策略是聲明性的,而且其配置是通過 XML 配置描述符來實現(xiàn)的。因此,您的應用程序不會受到影響,并保持與 J2EE 規(guī)范的兼容性和移植性,同時還從 WebSphere 的 servlet 及 JSP 的緩存機制中得到性能的優(yōu)化。

    從 servet 及 JSP 的動態(tài)緩存機制得到的性能的提高是顯而易見的,這取決于應用程序的特性。Cox 和 Martin [Cox] 指出對一個現(xiàn)有的 RDF(資源描述格式)站點摘要 (RSS)servlet,當使用動態(tài)緩存時,其性能可以提高 10%。請注意這個實驗只涉及到一個簡單的 servlet,這個性能的增長量可能并不能反映一個復雜的應用程序。

    為了更多地提高性能,將 WebSphere servlet/JSP 結果緩存與 WebSphere 插件 ESI Fragment 處理器、IBM HTTP Server Fast Response Cache Accelerator (FRCA) 和 Edge Server 緩存功能集成在一起。對于繁重的基于讀取的工作負荷,通過使用這些功能可以得到許多額外的好處。(請參見參考資料中的在 [Willenborg] 內(nèi)描述的性能的提高)

    12. 為了提高程序員的工作效率,將 CMP 實體 bean 作為 O/R 映射的首選解決方案.

    通過 WebSphere 框架(readahead、緩存、隔離級別等)優(yōu)化性能。如果可能,有選擇的應用一些模式來達到提高性能的目的,例如 Fast-Lane 閱讀器 [Marinescu]。

    對象/關系(O/R)映射是使用 Java 創(chuàng)建企業(yè)級的應用程序的基礎。幾乎每個 J2EE 應用程序都需要一些類型的 O/R 映射。J2EE 廠商提供一種 O/R 映射機制,這種機制在不同的廠商間是可移植的,高效的,并且能夠被一些標準及工具很好地支持。這就是 EJB 規(guī)范中的 CMP(容器管理的持久性)部分。

    早期的 CMP 實現(xiàn)以表現(xiàn)不佳及不支持許多 SQL 結構而著稱。然而,隨著 EJB 2.0 及 2.1 規(guī)范的出現(xiàn),以及被一些廠商所采納,并且隨著像 IBM WebSphere Studio Application Developer 的出現(xiàn),這些問題已經(jīng)不再是問題了。

    CMP EJB 組件現(xiàn)在已經(jīng)被廣泛地應用于許多高性能的應用程序中。WebSphere 包括一些優(yōu)化功能以提高 EJB 組件的性能,優(yōu)化功能包括:對生命周期的緩存和 read-ahead 能力。這兩者優(yōu)化功能都是配置時的選項,并且不需要對應用程序進行修改或者影響可移植性。

    處于緩存狀態(tài)的生命周期緩存 CMP 狀態(tài)數(shù)據(jù)并提供基于時間的無效性。從處于緩存狀態(tài)的生命周期得到的性能提高可以達到選項 A 的緩存性能,并且仍然可以為您的應用程序提供可伸展性。Read-ahead 能力和容器管理的關系結合使用。這個特性通過在相同的查詢中隨意地檢索相關的數(shù)據(jù)作為父數(shù)據(jù)而減少與數(shù)據(jù)庫的交互。如果相關的數(shù)據(jù)要通過使用并發(fā)的查詢來訪問的話,這種方法可以得到性能的改進。[Gunther]提供了詳細的描述以及通過這些特性得到的性能提高的細節(jié)。

    此外,為了完全優(yōu)化您的 EJB 組件,當指定隔離級別時要特別注意。盡可能使用最低的隔離級別,并且仍然保持您的數(shù)據(jù)的完整性。較低的隔離級別可以提供最佳的性能,并且可以降低出現(xiàn)數(shù)據(jù)庫死鎖的危險。

    這是目前最有爭議的最佳實踐。已經(jīng)有大量的文章贊揚 CMP EJB,同樣的貶斥聲也不絕于耳。然而,這里最基本的問題是數(shù)據(jù)庫開發(fā)是困難的。當您開始使用任何持久性解決方案之前,您需要掌握查詢以及數(shù)據(jù)庫鎖定如何工作這些基礎知識。如果您選擇使用 CMP EJB,您要確保您已經(jīng)通過一些書籍(例如 [Brown] 和 [Barcia])知道如何使用它們。在鎖定及爭用方面有一些微妙的交互難以理解,但是,在您耗費一定的時間及努力后會將其掌握的。

    結束語
    在這個簡短的摘要中,我們已經(jīng)向您介紹了 J2EE 中的核心模式和最佳實踐,這使得 J2EE 開發(fā)成為一種可管理的過程。盡管我們并沒有給出所有在實踐中使用這些模式的必要細節(jié),但是我們希望能夠給您足夠的指點和指導,以幫助您決定下一步要做什么。


    Kyle Brown
    , 高級技術成員, IBM Software Services for WebSphere
    Keys Botzum, 高級顧問/IT 專業(yè)人員, IBM Software Services for WebSphere
    Ruth Willenborg, 高級經(jīng)理, IBM WebSphere Performance

    引自網(wǎng)絡



    posted on 2007-01-06 09:25 java_蟈蟈 閱讀(130) 評論(0)  編輯  收藏

    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導航:
     
    主站蜘蛛池模板: 久久久久久亚洲av成人无码国产| 亚洲中字慕日产2021| 国产在线观看xxxx免费| 亚洲AV人无码综合在线观看| 成年人视频免费在线观看| 亚洲精品第一国产综合亚AV| 国产精品亚洲精品日韩已方| 久久午夜羞羞影院免费观看| 亚洲欧洲av综合色无码| 国外亚洲成AV人片在线观看| 亚洲国产精品免费在线观看| 美美女高清毛片视频黄的一免费| 亚洲国产精品一区二区第一页| 国产精品成人免费一区二区| 久久久久久毛片免费看| 亚洲一卡2卡三卡4卡无卡下载| 亚洲爆乳精品无码一区二区三区| 在线免费观看视频你懂的| 99久久免费国产精品热| 亚洲精品一卡2卡3卡四卡乱码| 亚洲AV中文无码乱人伦下载 | 18禁超污无遮挡无码免费网站国产| 一区二区三区免费在线视频 | 亚洲人成人77777在线播放| 亚洲成a人一区二区三区| 3344免费播放观看视频| 手机永久免费的AV在线电影网| 亚洲免费网站在线观看| 亚洲精品V欧洲精品V日韩精品 | 亚洲人成电影在线观看青青| 亚洲中文无韩国r级电影| 无码免费午夜福利片在线 | 日韩电影免费在线| 无码av免费网站| 无码日韩人妻AV一区免费l| 国产成人精品日本亚洲直接| 亚洲成a人片在线观看无码| 免费在线观看黄网站| 最近2019中文字幕免费看最新| 一级毛片在线免费观看| 女人裸身j部免费视频无遮挡|