構建生產質量EAR文件的最佳實踐

作者:Hussein Badakhchani
時間:2008213

 

簡介

封裝應用程序以便在生產服務器上部署是Java EE項目的一個組成部分。隨着越來越多的項目在國外開發,企業對清晰且可調整封裝規範的需求已經變得更加重要。沒有正確封裝的應用程序會導致不十分細微的錯誤,迫使專業人員花費很長時間進行分析進行解決。這些問題常常是斷斷續續的——例如,不同的部署機制(有一些適用於WebLogic Server)可能掩蓋部署錯誤,也可能觸發部署錯誤。

由於人們普遍忽視因封裝不好和缺少清晰的錯誤消息所引起的問題的嚴重性,這些問題也演變得更加複雜。迫於完成應用程序部署的壓力,部署失敗的原因時常受到人們的忽視。好的WebLogic管理員會通過一個工作區來完成部署,但這意味着需要重新部署應用程序。但是,如果沒有確定失敗的根源並加以解決,那麼在後面的測試階段,相同的問題還會出現,這樣解決起來可能更費時代價更高,同時還會增加無法按時交付項目的風險。在最壞的情況下,人們甚至認爲方案部署失敗不是是故障,並且接受它是應用程序行爲的一部分。

Java EE應用程序組裝和部署

在開始有關部署的Java EE 5規範的細節之前,需要理解規範的目的。在該規範的第8章“Application Assembly and Deployment”清楚地說明了其目的:“本章指定了組裝封裝和部署Java EE應用程序的Java PlatformEnterprise Edition (Java EE)要求。這些要求的主要目的是將可伸縮的模塊化應用程序組裝和可移植的Java EE應用程序部署提供到任何Java EE產品中。”

一般而言,規範涉及平衡各涉衆之間的需求,可以通過平臺角色識別它們,例如部署人員系統管理員和工具提供者。這種平衡作用,或者說得不好聽一點就是妥協,向最終用戶提供了一些靈活性,但其代價是增加了成本。因爲封裝細節由用戶決定,所以不同應用程序的封裝可能會有極大的差異,特別是對於那些不顧一切的項目團隊。我們要熟悉規範以確保必要時嚴格遵守並調整我們施加於它的各種限制。

Java EE應用程序

Java EE應用程序由最多四種Java EE模塊和一個可選的應用程序部署描述符組成。這些模塊包括:

1.        Enterprise JavaBeanEJB)模塊

2.        Webapp模塊

3.        應用程序客戶端模塊

4.        Resource Adapter模塊

與它們的父應用程序組件一樣,這些模塊所擁有的目錄結構和的部署描述符符合所有Java EE容器的預期。還有一個選項可包含特定於容器的部署描述符。例如,Webapp模塊能夠包含一個weblogic.xml部署描述符。下圖給出了三個最常見的應用程序組件的標準結構和部署描述符:EARWAREJB

 

 

 

1. EAR文件結構

2. WAR文件結構

3. EJB文件結構

爲生產環境封裝最佳實踐

將應用程序部署到生產環境時,安全性能和操作的敏捷性是最重要的考量。WebLogic管理員需要能夠快速地部署應用程序而且儘可能少的人工干預。滿足這些要求並且不需要修改代碼的方法是,使用部署描述符、應用服務器配置並將所有項目準確且一致地封裝到應用程序中。

下面我們將回顧一個相當優秀的封裝最佳實踐,它可確保將應用程序正確部署到WebLogic域。當然,應用程序部署後實際上是否工作就是開發人員的事情了。

顯然,並非所有的規範都適用於您的組織,而且您對它們也許並不都贊成;重要的是在第一個實例中有一些封裝規範並能夠調整它們。

PS001:以開放格式部署應用程序

以開放格式部署應用程序提供了以下的好處:

1.        WebLogic能夠更快地部署應用程序(相對於歸檔格式)。這提高了操作的敏捷性。

2.        它允許應用程序支持團隊更加方便快速地對配置文件做出修改(相對於歸檔格式)。

如果您的應用程序的部署時間是服務宕機的一個因素,那麼當容器解壓縮每個應用程序組件而消耗了大部分部署時間的時候,通過開發格式進行部署就能夠減少SLA違規的風險。如果您定期向服務器部署大量獨立的應用程序或大型應用程序包,這種好處就會放大。另一方面,如果應用程序部署沒有引起任何宕機,或只是偶爾有之,或您擁有JAR文件的簽署策略,那麼就不必考慮使用這個實踐。

PS002:在EAR中沒有重複的JAR文件

WebLogic遵循一種委託類加載模型。加載類的順序如下所示:

1.        系統類路徑加載器

2.        WebLogic服務器類路徑加載器

3.        應用程序類路徑加載器

4.        EJB類路徑加載器

5.        Webapp類路徑

這意味着位於APP-INF/libJAR文件對於Web應用程序將是可見的。APP-INF/libWEB-INF/lib中都不應該存在JAR文件。這增加了可交付程序的大小增加了部署時間並且可能會造成類加載問題和部署失敗。

理論上,JAR文件都只應該定義在APP-INF/lib中,除非迫切需要爲EAR文件中不同的模塊部署不同版本的JAR文件。

有關更多信息,請參見WebLogic Server 加載 機制。

PS003EAR中不得包含JSP未處理的/未編譯的註釋和源文件

在生產環境使用編譯器配置WebLogic服務器是一個安全隱患,同時在系統或WebLogic類路徑上包含tools.jar也是不安全的。使用預編譯的工件消除了配置編譯器的需要,也減少了應用程序初始化時間,改善了用戶初次訪問時感覺到的應用程序響應時間。確保所有工件在構建時被編譯也就意味着在編譯時間(而不是一旦應用程序已經部署)編譯時錯誤被識別和修正。

由於這些原因,EAR中的所有工件必須在完全編譯之後才能進行部署。必須使用最新版的與您的項目所使用的WebLogic的版本兼容的BEA Appc 工具編譯JSP。必須使用項目所使用的JDK版本提供的該版本的 apt 處理和編譯註釋。

有趣的是,這個實踐的一個反對意見來自堅持不編譯註釋的一個開發人員。我讓他訪問Sunapt工具網站,那裏寫明“apt首先運行註釋處理器,該處理器能產生新的源代碼和其他文件。接着,apt可以引起原始文件和生成文件的編譯,這就使開發過程更輕鬆了。”有些開發人員書生氣十足,令人好笑。澄清一下,編譯或處理的語義學會令人分心。問題是要確保只有版本化的二進制文件被部署到運行的服務器。

我已經在做幾個項目,其中tools.jar被留在類路徑上,WebLogic Server控制檯應用程序自身如果沒有被正確處理的話,則和它有一個依賴關係。WebLogic Server 9用戶應該知道這一點。

PS004:由系統或WebLogic類路徑提供的JAR文件不能包括在EAR

包括在應用程序中的WebLogic類路徑或系統上的JAR文件可能導致類加載問題——如果這些類加載器上的JAR文件被基礎架構團隊升級的話。它還會增加可交付程序的大小和部署時間(見PS001PS002)。如果您曾經不得不將JAR文件部署到系統類路徑上,那麼您應該確保這樣做有正當理由。在系統類路徑上管理JAR文件是一種開銷,因此最好避免如此。

PS005:確保所有EAR文件都有一個weblogic-application.xml描述符

使用WebLogic擴展的應用程序必須包括一個weblogic-application.xml描述符。如果EAR包括web應用程序模塊,那麼webapp.encoding.defaultwebapp.encoding.usevmdefault必須被明確定義以確保應用程序的可移植性並消除應用程序使用的特徵碼的任何模糊性。雖然在Java EE規範中,不提供特定於容器的部署描述符是完全可以接受的,但是在實踐中省略這些描述符可能在容器的部署代碼中暴露bug

當我看到沒有包含特定於容器的部署描述符的應用程序時,這就表明了應用程序沒有完成或者缺少對於如何以及在哪裏部署應用程序的關注。

PS006:確保所有WAR文件都有一個weblogic.xml描述符

weblogic.xml部署描述符至少應該在以下元素中包含有效且非空的自變量:

對於在WAR文件中包含一個weblogic.xml部署描述符的抵制總是令我喫驚。在向開發人員和他們的管理者解釋爲何包含此文件是一個良好的實踐的時候,他們完全可以從WebLogic的例子中複製一個文件到源控制並部署應用程序。歸根結底,未包含weblogic.xml部署描述符會導致一些我所見過的我接觸過的所有版本的WebLogic Server最難以解決的和代價高昂的 部署失敗

在我最近遇到的一個案例中,某應用程序並未附帶weblogic.xml部署描述符。但當應用程序需要在開發人員自己PC以外的機器上運行的時候,它就需要正確定義security-role-assignment元素。顯然,該缺陷與應用程序有關,但它卻是可能破壞部署這個問題的一個好例子。在許多組織中,假設負責應用程序部署的WebLogic管理員知道該元素要求的值應該是什麼是沒有理由的。然而,如果錯誤消息中包含了部署描述符,那麼也許會爲管理員提供一個解決此問題的機會。

PS007:確保所有EJB文件都有一個weblogic-ejb-jar.xml描述符

weblogic-ejb-jar.xml部署描述符至少應該在以下元素中包含有效且非空的自變量:

另外,原因與PS005PS006相同,即便您的應用程序無需任何特定於容器的特性,包含特定於容器的部署描述符也是一個良好的實踐。

PS008EAR文件中不能包含構建工件

build.xml文件和pom.xml文件等構建工件必須從所有的可部署包中濾除。此規範確實是一個良好的管理措施;不要部署任何超出您需要的東西。在一個包中尋找build.xml文件和pom.xml文件是一個散亂的構建過程。如果您的可交付程序將要發送給第三方,那麼其中還存在一個實際的安全問題。

PS009EAR中不能包含測試工件

所有測試工件都應該從可部署包中移除,例如JUnit系列的JAR文件及使用它們的測試用例。還有,不要部署任何多餘的東西,僅僅滿足自己的需求即可。包含這些文件會不必要地增加應用程序包的大小,使結構變得散亂。

PS010:在EAR中不能包含靜態內容

在使用代理Web服務器提供靜態內容的環境中,靜態內容應該從EAR文件中移除。這樣可以確保快速檢測出基礎架構堆棧的錯誤配置和錯誤代碼,以允許WebLogic提供靜態內容。如果您的應用程序需要使用大量靜態內容,由於它能對部署時間產生影響(見PS001),則這一點就尤爲重要。

PS011:配置文件的命名和位置必須一致

理論上,存儲於平面文件中的與應用程序環境相關的應用程序配置應該存儲在應用程序部署描述符中。如果應用程序確實要求使用特定的屬性文件來存儲配置信息,那麼這些文件的命名和位置必須保存一致。稍後,我將在實現指導中詳細闡述這一點。與此有關的一點是我將盡量減少在Java命令行指定的配置應用程序 的環境參數的使用。

PS012EAR中不能包含容器外部的JAR文件

部署在生產基礎架構上的任何EAR都不能使用應用程序容器外部實現中的JAR文件。發現在容器內運行代碼困難的開發人員會使用容器外測試。這種做法的一個令人遺憾的結果就是容器外實現使用的JAR(提供Java EE標準的接口和實現類——例如JTAservlet規範JAR)被包含在應用程序包中。部署應用程序之後,這便會導致各種各樣的類加載問題——特別是如果應用程序試圖管理自己的類加載。

PKS013:禁止使用MANIFEST.MF文件中的Class-Path頭部裝載庫

當使用JARManifest文件中的Class-Path頭部時,管理類路徑和類迴轉就變得過於複雜。相關的JAR文件應該位於應用程序的APP-INF/lib文件夾中或者位於EAR文件部署描述符的library-directory元素定義指定的目錄中。

PS014EAR命名和版本號必須符合公司的命名法

確保應用程序EAR命名一致,並且符合公司的命名法命名標準和規約。這將簡化應用程序部署和其他與應用程序EAR有關的流程的自動化。

PS015: EAR中的Web應用程序模塊必須與它們的上下文根同名並最終以.war爲擴展名

遵循此實踐,應用程序支持團隊和構建工具只需通過名稱便可快速確定應用程序的上下文根。還可以輕鬆地標識應用程序的靜態內容。

實現指導

任何一套規範都有助於提供參考實現。在本節中,我們將介紹如何實現已定義規範的一個子集。我們將討論PS003PS005PS006PS007PS010PS011

PS003:移除未編譯的文件

EAR中不能包含JSP未編譯的註釋和其他任何源文件。爲了使WebLogicJSP請求委託給經過編譯的類文件,下面兩節代碼必須添加到web應用程序模塊的web.xml文件中。

<servlet>
    <servlet-name>JSPClassServlet</servlet-name>    
    <servlet-class>weblogic.servlet.JSPClassServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>JSPClassServlet</servlet-name>
    <url-pattern>*.jsp</url-pattern>
</servlet-mapping>

PS005:包含weblogic-application.xml部署描述符

這是一個weblogic-application.xml描述符示例。

<?xml version="1.0" encoding="UTF-8"?>
<weblogic-application xmlns="http://www.bea.com/ns/weblogic/90"
  xmlns:j2ee="http://java.sun.com/xml/ns/j2ee"   
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
  xsi:schemaLocation="http://www.bea.com/ns/weblogic/90 http://www.bea.com/ns/weblogic/90/weblogic-application.xsd">
  <application-param>
    <param-name>webapp.encoding.default</param-name>
    <param-value>UTF-8</param-value>
  </application-param>
</weblogic-application>

PS006:包含web.xml部署描述符

這是一個web.xml描述符示例。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.4"
  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
  <description>
    The Monitor application is used by WhatsIt infrastructure for system validation testing.
  </description>
  <servlet>
    <servlet-name>JSPClassServlet</servlet-name>
      <servlet-class>weblogic.servlet.JSPClassServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>JSPClassServlet</servlet-name>
    <url-pattern>*.jsp</url-pattern>
  </servlet-mapping>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  <error-page>
    <error-code>500</error-code>
    <location>/error.jsp</location>
  </error-page>
  <error-page>
    <error-code>404</error-code>
    <location>/error.jsp</location>
  </error-page>
</web-app>

PS007包含web.xml部署描述符

weblogic-ejb-jar.xml描述符示例:

<?xml version="1.0" encoding="UTF-8"?>

<weblogic-ejb-jar xmlns="http://www.bea.com/ns/weblogic/90"
  xmlns:j2ee="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.bea.com/ns/weblogic/90 http://www.bea.com/ns/weblogic/90/weblogic-ejb-jar.xsd">
  <weblogic-enterprise-bean>
    <description>Example EJB</description>
    <ejb-name>BeanManagedAccountEJB</ejb-name>
    ....
<weblogic-ejb-jar>

PS010EAR中不能包含靜態內容

靜態內容應該通過JAR文件交付,其結構如下:

<Webapp Content>
     |--css
     |--images
     |--index.html

index.html文件應該將用戶重定向到Web應用程序模塊的web.xml文件的<welcome-file list>元素的值。例如,如果webapp模塊使用JSF,則index.html應如下所示:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
  <head>
    <title>Redirect to JSF controller</title>
    <meta http-equiv="REFRESH" content="0;url=http://mydomain.com/webapp/index.faces"/>
  </head>
  <body>
  </body>
</html>

這將確保分解JAR文件之後,所有Web應用程序都將有自己靜態內容,位於一個一致且可可識別的目錄結構中。

PS011:配置文件的名稱和位置

所有EAR的應用程序配置都應該保存在一個名爲env.properties的文件中。這些文件都必須位於APP-INF/lib/classes路徑下。

實現封裝最佳實踐

具備了一組封裝最佳實踐和實現指導之後,應該如何來實現它們呢?顯然,您不想在每一個新構建的應用程序上花費數小時的時間。

一個查看應用程序包的封裝規範符合度的好時機正是在應用程序被構建之後,所以編寫一個自定義 Ant 任務或擴展Maven Verifier plugin 很可能是最佳解決方案。並且,請記住:臨時或無限期同意讓步的理由總是很充分,這將允許應用程序違犯您的規範。任何的違規事件都應該與許可的截止日期一起記錄在應用程序的發佈註釋中。

結束語

此處詳述的封裝最佳實踐並非說明目的——您應該以它們爲指導實現自己的規範。毫無疑問,這與您的方法會有一定程度的衝突,因此請確保能夠調整它們。歸根結底,如果您負責向服務器成功部署應用程序,那麼封裝規範是實現目標必不可少的工具。

參考資料

Hussein Badakhchani 是一名諮詢顧問和中間件分析師,他在軟件設計開發管理和支持方面擁有十年以上經驗。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章