首先,以下是本文涵蓋專案的一些假設
Ant 也是 IDE 的絕佳輔助工具;一種執行所有部署管理以及乾淨、自動化建置的方法。但一個好的現代 IDE 本身就是一個生產力工具,您應該繼續使用。Ant 只是讓團隊在 IDE 選擇上擁有更多自由,例如「您可以在開發中使用任何您想要的,但部署建置使用 Ant」。現在,許多現代開源和商業 IDE 都包含 Ant 支援(包括 jEdit、Forte、Eclipse 和 IDEA),開發人員可以使用一個很棒的 IDE,而 Ant 則提供嚴謹且可攜式的建置流程,整合到工具中。
使用標準目標名稱,很容易建置包含的 Ant 建置檔案,只要使用 ant 工作將工作交給下方的類別即可。例如,可以從父目錄將 clean 目標傳遞給 intf 和 impl 子目錄
<target name="clean" depends="clean-intf, clean-impl"> </target> <target name="clean-intf" > <ant dir="intf" target="clean" /> </target> <target name="clean-impl"> <ant dir="impl" target="clean" /> </target>如果您給予目標一個 description 標籤,然後呼叫 ant -projecthelp,它會將所有工作列為「主要目標」,並將所有沒有描述的工作列為子目標。因此,描述所有進入點非常有用,即使在專案變得龐大且複雜之前。
Ant 讓你呼叫 JUnit 任務,它會單元測試你的團隊所撰寫的程式碼。自動化測試一開始看起來像是額外的負擔,但 JUnit 讓撰寫單元測試變得如此容易,你幾乎沒有理由不這麼做。花時間學習如何使用 JUnit,撰寫測試案例,並在 Ant 的「test」目標中整合它們,這樣你的團隊每天或每小時的建置就可以自動套用測試。使用 Ant 進行 Java 開發 中可以免費下載的章節之一,會教你如何從 Ant 內部使用 JUnit。
一旦你加入從 SCM 系統擷取程式碼的方法,無論是作為 Ant 任務、在某些 shell 腳本或批次檔案中,或透過某些持續整合工具。整合測試程式碼可以是純粹的 Ant 任務,在任何專門執行該任務的電腦上執行。這對於驗證建置和單元測試在不同於一般開發電腦的目標上運作非常理想。例如,即使沒有開發人員願意在有選擇的情況下使用 Win95/Java1.1 組合,但仍然可以使用它。
系統測試比單元測試更難自動化,但如果你可以撰寫 Java 程式碼來對系統的大部分施加壓力,即使程式碼無法作為 JUnit 任務執行,那麼 java 任務可以用來呼叫它們。最好指定你想要為這些測試使用新的 JVM,這樣重大的崩潰才不會中斷整個建置。Junit 擴充功能,例如用於網頁的 HttpUnit,以及用於 J2EE 和 servlet 測試的 Cactus,有助於擴充測試架構。為了適當地測試,你仍然需要投入大量精力讓它們與你的專案一起運作,並衍生出絕佳的單元、系統和回歸測試,但你的客戶會因為你出貨運作良好的軟體而愛你。
跨平台 Ant 的常見障礙是使用不可攜式的命令列工具 (exec 任務)、路徑問題,以及硬式編碼在事物的所在位置。
命令列呼叫任務讓您指定您希望程式碼在上面執行的平台,因此您可以為您鎖定的每個平台撰寫不同的任務。或者,平台差異可以在 Ant 呼叫的某些外部程式碼中處理。這可以是新任務中編譯的 Java,或外部腳本檔案。
平台之間的這種差異(實際上,整個 Java 類別路徑範例)可能會造成數小時的樂趣。
Ant 減少了路徑問題;但並未完全消除它們。您也需要付出一些努力。處理路徑名稱的規則是「處理類似 DOS 的路徑名稱」、「處理類似 Unix 的路徑」。磁碟機 -「C:」- 在基於 DOS 的方塊中處理,但將它們放入 build.xml 檔案中會破壞所有可移植性。相對檔案路徑更具可移植性。分號可用作路徑分隔符 - 如果您的 Ant 呼叫包裝程式包含命令列中定義的屬性中的一系列 jar,則此事實很有用。在建置檔案中,您可能會發現透過列出個別檔案(使用 location= 屬性)或在類別路徑定義中包含 *.jar 的檔案集來建立類別路徑會更好。
還有一個 PathConvert 任務,它可以將完全解析的路徑放入屬性中。為什麼要這樣做?因為這樣您就可以使用該路徑以其他方式 - 例如將其作為參數傳遞給您正在呼叫的某些應用程式,或使用替換任務將其修補到本機化指令碼或批次檔案中。
請注意,DOS 下屬的檔案系統不區分大小寫(除了針對 NTFS 執行的 WinNT POSIX 子系統的模糊差錯),而且 Windows 假裝所有具有四個或更多字母的檔案副檔名也是三個字母的副檔名(請在您的 Java 目錄中嘗試 DELETE *.jav,以查看此情況的災難性範例)。
Ant 關於大小寫敏感性的政策是實現底層檔案系統的任何內容,以及處理檔案副檔名的方式是 *.jav 找不到任何 .java 檔案。當然,Java 編譯器區分大小寫 - 您不能在「examplethree.java」中實作類別「ExampleThree」。
某些任務僅在一個平台上執行 - Chmod 是經典範例。這些任務通常只會在不受支援的平台上產生警告訊息 - 目標的其他任務仍會被呼叫。其他任務會降低其在平台或 Java 版本上的功能。特別是,任何調整檔案時間戳記的任務都無法在 Java 1.1 上正確執行。可以這樣做的任務 - 例如 Get、Touch 和 Unjar/Unwar/Unzip - 會降低其在 Java1.1 上的功能,通常會改用目前的時戳記。
最後,Perl 是用來包裝跨平台 Java 呼叫,而非批次檔案的好地方。它包含在大部分 Unix 發行版中,而且是 ActiveState 的 Win32 平台 的簡單下載。具有 .pl 副檔名的 Perl 檔案,第 1 行註解中的常見 Unix 路徑至 perl,並標示為可執行,可以在 Windows、OS/2 和 Unix 上執行,因此可以從 Ant 呼叫而不會有問題。Perl 程式碼可以保留以解決其自己的平台問題。重新散發 Perl 程式碼時,別忘了將檔案的行尾設定為適當的平台;fixCRLF 可以為您執行這項工作。
另一個好策略是使用統一的目錄樹,並在該樹中加入額外的工具。所有參考都可以相對於該樹。如果預期團隊成員將專案中的目錄加入他們的路徑,則命令列工具可以包含在其中,包括 Ant exec 工作呼叫的那些工具。將所有內容置於原始碼控制之下,您便可以從 CVS 或等效工具中取得建置/執行環境的一站式商店。
Ant 可以 Jar、Tar 或 Zip 檔案以供部署,而 War 工作則延伸 jar 工作以改善 servlet 部署。Jlink 是 jar 產生檔案,讓您可以合併多個子 jar 檔。這對於建置流程非常理想,其中子專案會產生個別的 jar 檔,但最終輸出是合併的 jar 檔。Cab 可以用於 Win32 方塊,以建置 cab 檔案,如果您仍必須針對 IE 部署,這將很有用。
ftp 工作讓您可以將東西移至伺服器。小心不要在建置檔案中放入 ftp 密碼,具有嚴格存取控制的屬性檔案會稍微好一點。FixCRLF 工作通常是有用的中間步驟,如果您需要調整檔案的行尾。WebDav 工作已經討論很長一段時間,它將提供更安全的上傳至網路伺服器,但它仍在待辦事項清單中。有傳言說在 jakarta-slide 函式庫中有一個這樣的任務。由於 MacOS X、Linux 和 Windows XP 都支援 WebDAV 檔案系統,您甚至可以使用 copy 透過防火牆進行部署。
EJB 部署由 ejb 任務提供協助,而 serverdeploy 套件可以部署到多個伺服器。Ant 的普及性鼓勵供應商製作自己的部署任務,並隨伺服器重新分發。例如,Tomcat4.1 安裝包含用於部署、取消部署和重新載入 Web 應用程式的任務。
最後,當然還有使用 Copy 和 Copydir 將檔案複製到目的地,或使用 Mail 或支援附件的 MimeMail 將檔案傳送給人員或處理程序。在一個專案中,我們的團隊甚至使用 Ant 透過建置,接著執行一組長 Copy 任務來建置 CD 映像,結果出乎意料地好,肯定比我們將檔案寄到 myrealbox.com 上的免費電子郵件服務,然後從遠端的 Web 瀏覽器拉取檔案來得容易,而我們是在透過 SSH 執行 WinNT 遠端桌面連線,再透過 SSH 進行通道連線。
bin | 共用二進位檔、指令碼 - 將其放在路徑上。 |
build | 這是建置的樹狀結構;Ant 建立它,並可以在「清理」專案中清空它。 |
dist | 發行版本輸出會放在這裡;目錄是在 Ant 中建立,而清理會清空它 |
doc | 手工製作的文件 |
lib | 匯入的 Java 函式庫會放在這個目錄中 |
src | 原始碼會放在這個樹狀結構下,以符合套件名稱的階層結構。<javac> 的相依性規則需要這樣做。 |
Javadoc 輸出可以導向 build/ 下方的 doc/ 資料夾,或導向 doc/javadoc。
若要在子專案中仍然擁有單一建置,請使用父層 build.xml 檔案,它會呼叫進入子專案。
如果不同的團隊擁有不同的程式碼存取/承諾權限,這種樣式會運作良好。風險在於,透過給予子專案額外的迴旋餘地,您可能會得到不相容的原始碼、函式庫、建置程序,並增加您的工作負載和整體的整合悲劇。
保留對相當鬆散整合的專案集合的控制的唯一方法,是擁有完全自動化的建置和測試程序,以驗證所有內容仍然相容。Sam Ruby 為所有 apache java 函式庫執行一個,並在發生問題時寄電子郵件給所有人;您的專案可能可以使用 Cruise Control 來進行自動化、持續、背景建置程序。
如果每個人都彼此信任,且子專案並非過於龐大或複雜,則此專案樣式會很有效。風險在於,隨著專案進展,可能會需要拆分為更鬆散結合的設計,但等到意識到這一點時,排程壓力和交錯的建置檔案會讓執行拆分變得幾乎不可能。如果發生這種情況,請持續執行,直到有時間重構專案目錄結構為止。
更新通常需要變更 build.xml 檔案。大多數變更都旨在向後相容,但有時必須進行不相容的變更。這就是為什麼在重大里程碑後的平靜期進行更新很重要的原因。這也是為什麼在 CVS 樹中包含 ant.jar 和相關檔案有助於確保舊版本的軟體仍可建置的原因。
最積極的策略是取得 Ant 來源的每週或每日快照,建置它並使用它。這會強制您更定期地調整 build.xml 檔案,因為新的任務和屬性可能需要一段時間才能穩定下來。您真的必須想要新功能、享受無償的額外工作或樂於讓同事感到不安,才能採取這種方法。
一旦你開始使用新的任務擴充 Ant,你會突然發現拉取定期建置變得更誘人。最新的 Ant 建置永遠都是撰寫擴充功能的最佳平台,因為你可以利用基礎類別的定期增強功能。它也可以防止你浪費時間在已經完成的事情上。一個新提交的任務,例如與 EJB 引擎、SOAP 伺服器交談或僅將文字檔案轉換成大寫,可能幾乎完全符合你的需求,因此請採用它、增強它並提供增強功能給全世界。這肯定比在 Ant 0.8 中孤立地開始處理你的「文字大小寫轉換器」任務、在六個月後宣布它的存在,然後發現你得到的不是讚美而是對現有實作的有用指標來得好。參與這個流程的最後一個好處是,它讓你的任務更容易加入 Ant CVS 樹狀結構,提前 Ant 採用你為讓專案運作而需要的所有變更的日期。如果發生這種情況,你可以恢復到官方 Ant 版本,並繼續處理所有其他危機。
你也應該加入 dev 郵件清單,因為這是其他開發人員張貼其工作、問題和經驗的地方。訊息量可能相當大:一天超過 40 則訊息,因此請考慮將它轉發到你不常使用的電子郵件地址。而且不要讓團隊中的每個人都訂閱;它可能會造成過多的干擾。
使用 Ant 的好處首先在於,相同的安裝目標可以用於你的本機建置檔案(透過 install.xml 檔案的 ant 呼叫),其次在於,撰寫基本的安裝目標相當容易。這種方法的缺點是,目的地必須正確預先安裝最新版本的 Ant,而且 Ant 不允許你妥善處理失敗,而一個好的安裝程式就是關於在事情出錯時進行處理,從檔案正在使用到 jar 版本不同。這表示 Ant 不適合封裝軟體,但它確實適用於部署和安裝到你的本機伺服器。
我參與的一個大型建置專案有一個 Bluestone 應用程式伺服器的 Ant 安裝建置檔案,它會關閉單一電腦上應用程式伺服器的所有四個執行個體,將新版本的 war 檔案(包含日期戳記和建置戳記)複製到檔案目錄,清除目前已部署的 war 版本,然後安裝新版本。因為 Bluestone 會依需求重新啟動 JVM,所以這個指令碼就是你部署網路服務所需要的全部。在防火牆後面的系統上,我們透過使用 ftp 任務複製出 war 和建置檔案,然後使用 telnet 任務遠端呼叫建置檔案,進而提升部署流程的層級。結果是我們已經自動化了從我們的 IDE(Jedit)或命令列重新編譯和重新部署到本機伺服器的流程,這非常有價值。想像一下在你的 IDE 工具列上按下一個按鈕,就能建置、單元測試、部署,然後功能測試你的網路應用程式。
我後來新增了一個額外的技巧,即一個 junit 測試案例,用於執行安裝檢查清單。透過測試驗證網路磁碟機的存取權限、伺服器之間近似的時鐘同步、DNS 功能、產生可執行檔的能力以及其他所有問題點,安裝指令碼可以在安裝期間自動執行系統健全測試並報告問題。[相同的測試也可以從 JMX MBean 呼叫,但那是另一個故事]。
因此,Ant 僅在您控制的伺服器特殊情況下,才不是真正安裝工具的替代品,但在這種情況下,它確實讓您能將遠端安裝與您的建置整合。
有兩種包含機制,一種適用於所有解析器的醜陋機制,以及一種乾淨的機制。醜陋的方法是 Ant1.5 及更早版本中唯一可用的方法:-
<!DOCTYPE project [ <!ENTITY propertiesAndPaths SYSTEM "propertiesAndPaths.xml"> <!ENTITY taskdefs SYSTEM "taskdefs.xml"> ]> &propertiesAndPaths; &taskdefs;Ant1.6 中較乾淨的方法是 <import> 任務,它會將整個建置檔案匯入其他專案。實體包含範例幾乎可以用兩個匯入陳述式取代:-
<import file="propertiesAndPaths.xml"> <import file="taskdefs.xml">我們說幾乎是頂層宣告(屬性和任務定義)不會插入到 XML 檔案中,就在匯入陳述式所在的位置,而是新增到檔案的結尾。這是因為匯入程序會在主建置檔案被剖析後,在執行期間進行,而 XML 實體擴充則會在剖析程序期間處理。
<import> 任務會執行強大的動作,例如讓您覆寫目標,並使用 ant 屬性來命名要匯入檔案的位置。請參閱文件,以了解這些功能的具體資訊。
在您過度使用 XML 包含之前,請注意 ant 任務讓您可以在任何其他建置檔案中呼叫任何目標 - 並將您的所有屬性設定傳播到該目標。因此,您實際上可以擁有一組公用程式目標 - 「deploy-to-stack-a」、「email-to-team」、「cleanup-installation」,可以從您的任何主建置檔案中呼叫,也許使用細微變更的參數。確實,在幾個專案之後,您也許可以建立一個可重複使用的核心建置檔案,其中包含基本 Java 開發專案的核心目標 - 編譯、偵錯、部署 - 專案特定的建置檔案會使用自己的設定呼叫這些目標。如果您能達成此目標,那麼您絕對正在提升您的軟體成熟度階梯。經過一番努力,您也許可以從 SEI CMM 等級 0 組織「個人英雄主義還不夠」進步到 SEI CMM 等級 1,「專案只能因為個人英雄主義而成功」
注意,ant 會複製您的所有屬性,除非將 inheritall 屬性設定為 false。在該屬性存在之前,您必須小心命名所有建置檔案中的所有屬性定義,以防止呼叫者的屬性意外覆寫被呼叫的屬性,現在您只需要記得在 <<ant> 任務的所有使用中設定 inheritall="false" 即可。
擁有在 PROJECT_HOME 下的 CVS 控制函式庫樹上執行的自訂呼叫指令碼,也讓您可以在團隊中控制 Ant 版本 - 開發人員可以擁有其他 Ant 副本(如果他們想要的話),但 CVS 樹總是包含用於建置您的專案的 jar 組。
您也可以撰寫呼叫現有 Ant 指令碼的包裝指令碼。這是延伸它們的簡單方法。包裝指令碼可以新增額外的定義和命名明確的目標,重新定義 ANT_HOME,並通常讓開發更容易。請注意,Windows 中的「ant」實際上是「ant.bat」,因此應該從另一個批次檔案呼叫,並使用「CALL ant」陳述式 - 否則它永遠不會傳回您的包裝指令碼。
再進一步,考慮將 Ant Task 介面提供給程式碼,作為功能的次要、主要甚至唯一介面。Ant 實際上是 Java 應用程式的絕佳開機載入程式,因為它處理類別路徑設定,而且你可以重複使用所有內建的任務,進行前言和後記工作。有些專案,例如 XDoclet,只在 Ant 下執行,因為那是正確的位置。
偵錯/發布切換可以使用在編譯任務之前呼叫的名為「初始化目標」來處理,這些任務定義適當的屬性。Antcall 在這裡是技巧,因為它允許您在建置檔案中設定兩個屬性初始化路徑。
內部目標應用于建置程序
<target name="init-release" if="release.build"> <property name="build.debuglevel" value="lines,source"/> </target>然後您有依賴目標(例如「編譯」)依賴於這個條件目標;在那裡設定「預設」屬性,然後實際使用該屬性。由於 Ant 屬性是不可變的,因此如果執行發布目標,其設定將覆寫預設值
<target name="compile" depends="init,init-release"> <property name="build.debuglevel" value="lines,vars,source"/> <echo>debug level=${build.debuglevel}</echo> <javac destdir="${build.classes.dir}" debug="true" debuglevel="${build.debuglevel}" includeAntRuntime="false" srcdir="src"> <classpath refid="compile.classpath"/> </javac> </target>因此,我們現在有一個建置,其中發布模式僅包含檔案名稱和行偵錯資訊(對於錯誤報告很有用),而開發系統也包含變數。
定義專案名稱屬性很有用,可以在 init 任務中呼應它。這讓您可以在多檔案建置中找出中斷哪個 Ant 檔案。
哪些內容會進入內部 Ant 任務取決於您自己的專案。一個非常重要的策略是「透過參照降低路徑重新定義」 - 您可以透過給予它們 ID,然後透過「refid」屬性參照它們來重複使用路徑,您應該只需要在檔案中定義一次共用類別路徑;檔案集可以類似地重複使用。
一旦您設定好目錄結構,並定義 Ant 任務,就可以開始編碼。早期優先事項必須是設定自動化測試程序,因為這不僅有助於確保程式碼運作,它驗證建置程序正在運作。
如此而已。當新增原始檔時,不應需要變更建置檔,只有在您想要變更交付成果或建置程序的一部分時才需要變更。在某個時間點,您可能想要大量重新建構整個建置程序、重新建構專案等,但即使如此,您擁有的建置檔應作為分割建置檔程序的基礎,只要將共用屬性拉到所有建置檔都讀取的屬性檔中,保持目標名稱統一,並持續使用專案即可。重新建構原始碼控制系統通常是更困難的工作。
如果您的建置需要處理例外狀況,請查看 sound 監聽器,作為撰寫您自己的監聽器類別的簡單範例。複雜的條件式陳述可以透過讓其他項目執行測試,然後建置適當的 Ant 任務來處理。XSLT 可用於此目的。
您也需要某種變更控制程序,以抵抗不受控的功能蔓延。Bugzilla 是此目的的簡單且低成本工具,使用 Ant 和持續測試程序可以快速演進程式碼,以適應那些不可避免的變更。
有關此文件的相關問題,請使用 Ant 郵件清單。