好久沒更博了,最近研究了一下Ant打包機制,作一下記錄。首先簡要介紹一下Ant。
Ant是一個基于Java的生成(在軟體開發中用來将源代碼和其他輸入檔案轉換為可執行檔案的形式)工具,最常用的就是用Ant打包war檔案。在使用Ant打包之前需要搭建一個ant環境,大緻分為一下幾步:
1、安裝jdk并配置環境變量(JAVA_HOME、CLASSPATH、PATH);
2、下載下傳Ant并解壓;
3、建立環境變量ANT_HOME=解壓路徑,并在PATH後追加ANT_HOME目錄下的bin目錄(如ANT_HOME:D:\apache-ant-1.8.2,PATH:%ANT_HOME%\bin);
4、測試一下你的設定,開始–>運作–>cmd進入指令行–>鍵入 ant 回車,如果看到
Buildfile: build.xml does not exist!
Build failed
那麼你的Ant環境搭建成功。
使用Ant打包的好處是在多次調試運作中不需要手動的用javac 、copy 、jar、java來一次次的完成,可以批量地完成這些重複操作。是以,ant需要一個建構檔案來定義以上這些操作,建構檔案一般命名為build.xml,也可以使用其他自己定義的名字,但是在調用的時候需要加上-buildfile參數,如ant -buildfile mybuild.xml。下面介紹一下如何建立一個建構檔案。
Ant建構檔案是XML檔案。每個建構檔案定義一個唯一的項目(Project标簽)。每個項目下可以定義很多目标(target标簽),這些目标之間可以有依賴關系。當執行這類目标時,需要執行他們所依賴的目标。每個目标中可以定義多個任務,目标中還定義了所要執行的任務序列。Ant在建構目标時必須調用所定義的任務。任務定義了Ant實際執行的指令。Ant中的任務可以為3類。
(1) 核心任務。核心任務是Ant自帶的任務。
(2) 可選任務。可選任務實來自第三方的任務,是以需要一個附加的JAR檔案。
(3) 使用者自定義的任務。使用者自定義的任務實使用者自己開發的任務。
1、project标簽
每個建構檔案對應一個項目。project标簽時建構檔案的根标簽。它可以有多個内在屬性,就如代碼中所示,其各個屬性的含義分别如下。
(1) default表示預設的運作目标,這個屬性是必須的。
(2) basedir表示項目的基準目錄。
(3) name表示項目名。
(4) description表示項目的描述。
每個建構檔案都對應于一個項目,但是大型項目經常包含大量的子項目,每一個子項目都可以有自己的建構檔案。
2、target标簽
一個項目标簽下可以有一個或多個target标簽。一個target标簽可以依賴其他的target标簽。例如,有一個target用于編譯程式,另一個target用于聲稱可執行檔案。在生成可執行檔案之前必須先編譯該檔案,因策可執行檔案的target依賴于編譯程式的target。Target的所有屬性如下。
(1) name表示标明,這個屬性是必須的。
(2) depends表示依賴的目标。
(3) if表示僅當屬性設定時才執行。
(4) unless表示當屬性沒有設定時才執行。
(5) description表示項目的描述。
Ant的depends屬性指定了target的執行順序。Ant會依照depends屬性中target出現順序依次執行每個target。在執行之前,首先需要執行它所依賴的target。程式中的名為run的target的depends屬性compile,而名為compile的target的depends屬性是prepare,是以這幾個target執行的順序是prepare->compile->run。一個target隻能被執行一次,即使有多個target依賴于它。如果沒有if或unless屬性,target總會被執行。
3、mkdir标簽
該标簽用于建立一個目錄,它有一個屬性dir用來指定所建立的目錄名,其代碼如下:
<mkdir dir=”${class.root}”/>
通過以上代碼就建立了一個目錄,這個目錄已經被前面的property标簽所指定。
4、jar标簽
該标簽用來生成一個JAR檔案,其屬性如下。
(1) destfile表示JAR檔案名。
(2) basedir表示被歸檔的檔案名。
(3) includes表示别歸檔的檔案模式。
(4) exchudes表示被排除的檔案模式。
5、javac标簽
該标簽用于編譯一個或一組java檔案,其屬性如下:
(1).srcdir表示源程式的目錄。
(2).destdir表示class檔案的輸出目錄。
(3).include表示被編譯的檔案的模式。
(4).excludes表示被排除的檔案的模式。
(5).classpath表示所使用的類路徑。
(6).debug表示包含的調試資訊。
(7).optimize表示是否使用優化。
(8).verbose 表示提供詳細的輸出資訊。
(9).fileonerror表示當碰到錯誤就自動停止。
6、java标簽
該标簽用來執行編譯生成的.class檔案,其屬性如下。
(1).classname 表示将執行的類名。
(2).jar表示包含該類的JAR檔案名。
(3).classpath所表示用到的類路徑。
(4).fork表示在一個新的虛拟機中運作該類。
(5).failonerror表示當出現錯誤時自動停止。
(6).output 表示輸出檔案。
(7).append表示追加或者覆寫預設檔案。
7、war标簽
該标簽用來把javaweb項目打包成一個war檔案,在javaweb開發中經常用到,其屬性如下。
(1).destfile表示生成war檔案路徑。
(2).webxml表示web項目的配置檔案web.xml
8、delete标簽
該标簽用于删除一個檔案或一組檔案,去屬性如下:
(1).file表示要删除的檔案。
(2).dir表示要删除的目錄。
(3).includeEmptyDirs 表示指定是否要删除空目錄,預設值是删除。
(4).failonerror 表示指定當碰到錯誤是否停止,預設值是自動停止。
(5).verbose表示指定是否列出所删除的檔案,預設值為不列出。
9、copy标簽
該标簽用于檔案或檔案集的拷貝,其屬性如下。
(1).file 表示源檔案。
(2).tofile 表示目标檔案。
(3).todir 表示目标目錄。
(4).overwrite 表示指定是否覆寫目标檔案,預設值是不覆寫。
(5).includeEmptyDirs 表示制定是否拷貝空目錄,預設值為拷貝。
(6).failonerror 表示指定如目标沒有發現是否自動停止,預設值是停止。
(7).verbose 表示制定是否顯示詳細資訊,預設值不顯示。
以上是建構檔案中的常用标簽,還有很多标簽,在此不一一介紹
在建構檔案中為了辨別檔案或檔案組,經常需要使用資料類型,介紹幾種常用的資料類型。
1、fileset類型
Fileset 資料類型定義了一組檔案,并通常表示為fileset元素。不過,許多ant任務建構成了隐式的fileset,這說明他們支援所有的fileset屬性和嵌套元素。以下為fileset 的屬性清單。
(1).dir表示fileset 的基目錄。
(2).casesensitive的值如果為false,那麼比對檔案名時,fileset不是區分大小寫的,其預設值為true。
(3).defaultexcludes 用來确定是否使用預設的排除模式,預設為true。
(4).excludes 是用逗号分隔的需要派出的檔案模式清單。
(5).excludesfile 表示每行包含一個排除模式的檔案的檔案名。
(6).includes 是用逗号分隔的,需要包含的檔案模式清單。
(7).includesfile 表示每行包括一個包含模式的檔案名。
例如:
<fileset dir="${lib.dir}">
<include name="**/*.jar"/>
</fileset>
2、argument 類型
由Ant建構檔案調用的程式,可以通過arg元素向其傳遞指令行參數,如apply,exec和java任務均可接受嵌套arg元素,可以為各自的過程調用指定參數。以下是arg的所有屬性。
(1).values 是一個指令參數。如果參數種有空格,但又想将它作為單獨一個值,則使用此屬性。
(2).file表示一個參數的檔案名。在建構檔案中,此檔案名相對于目前的工作目錄。
(3).line表示用空格分隔的多個參數清單。
(4).path表示路徑。
3、path類型
Path元素用來表示一個類路徑,不過它還可以用于表示其他的路徑。在用作揖個屬性時,路經中的各項用分号或冒号隔開。在建構的時候,此分隔符将代替目前平台中所有的路徑分隔符,其擁有的屬性如下。
(1).location 表示一個檔案或目錄。Ant在内部将此擴充為一個絕對路徑。
(2).refid 是對目前建構檔案中某處定義的一個path的引用。
(3).path表示一個檔案或路徑名清單。
例如:
<path id="classpath">
<fileset dir="${lib.dir}">
<include name="**/*.jar"/>
</fileset>
</path>
4、filterset 類型
Filterset定義了一組過濾器,這些過濾器将在檔案移動或複制時完成檔案的文本替換。
主要屬性如下:
(1).begintoken 表示嵌套過濾器所搜尋的記号,這是辨別其開始的字元串。
(2).endtoken表示嵌套過濾器所搜尋的記号這是辨別其結束的字元串。
(3).id是過濾器的唯一标志符。
(4).refid是對建構檔案中某處定義一個過濾器的引用。
5、ervironment 類型
由Ant建構檔案調用的外部指令或程式,env元素制定了哪些環境變量要傳遞給正在執行的系統指令,env元素可以接受以下屬性。
(1).file表示環境變量值得檔案名。此檔案名要被轉換位一個絕對路徑。
(2).path表示環境變量的路徑。Ant會将它轉換為一個本地約定。
(3).value 表示環境變量的一個直接變量。
(4).key 表示環境變量名。
注意 file path 或 value隻能取一個。
提供一個我自己開發的建構檔案demo:
<?xml version="1.0" encoding="UTF-8"?>
<project name="webclient" default="war" basedir=".">
<property name="webapp.name" value="webclient"/>
<property name="src.dir" value="${basedir}/src"/>
<property name="lib.dir" value="${basedir}/WebContent/WEB-INF/lib"/>
<property name="class.dir" value="${basedir}/WebContent/WEB-INF/classes"/>
<property name="war.dir" value="${basedir}/war"/>
<!-- set class path -->
<path id="classpath">
<fileset dir="${lib.dir}">
<include name="**/*.jar"/>
</fileset>
</path>
<!-- clean class & war -->
<target name="clean">
<delete dir="${class.dir}" includes="**/*.class"/>
<delete dir="${war.dir}/${webapp.name}.war"/>
</target>
<!-- compile java -->
<target name="compile" depends="clean">
<mkdir dir="${class.dir}"/>
<javac srcdir="${src.dir}" destdir="${class.dir}" debug="true" includeantruntime="false">
<classpath refid="classpath"/>
</javac>
<copy todir="${class.dir}">
<fileset dir="${src.dir}" excludes="**/*.java"/>
</copy>
</target>
<target name="war" depends="compile">
<mkdir dir="${war.dir}"/>
<war destfile="${war.dir}/${webapp.name}.war" webxml="${basedir}/WebContent/WEB-INF/web.xml">
<fileset dir="${basedir}/WebContent">
<exclude name="**/*.java"/>
</fileset>
<!-- <lib dir="${lib.dir}"/> -->
<!-- <classes dir="${class.dir}"/> -->
</war>
</target>
</project>
建立了build檔案,就可以打包war、jar等檔案了。具體操作:進入dos指令環境->cd指令進入build.xml檔案所在目錄->執行指令ant -buildfile build.xml
出現如圖所示界面,說明war檔案打包成功。

細心的讀者可能會發現我的指令行中并沒有調用“ant”指令,而是運作了一個叫build.bat的批量處理檔案,并且我的ant路徑也是以參數傳遞的。不錯,我在ant.bat檔案外層自定義了一個build.bat檔案,在檔案中調用ant指令執行打包操作。這樣做是有好處的,下面先給出build.bat檔案,再說明這樣做的優勢。
@echo off
set JAVA_HOME=C:\Program Files (x86)\Java\jdk1.._17
set CLASSPATH=.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar
set work_dir=%~dp0%
rem set /p ANT_PATH=please input ant path:
set ANT_PATH=%
pushd %work_dir%
%ANT_PATH%/ant -buildfile build.xml
popd
可以看到,在檔案開頭我定義了兩個宏,指明jdk的配置資訊。這樣一來,使用者就不需要再配置jdk的環境變量了。假如你的電腦裡安裝了兩個版本的jdk,隻需要修改腳本檔案就可以輕松地在兩個版本jdk中運作。另外,以參數的形式傳入Ant的路徑,也省去了配置Ant的環境變量,這樣既友善後續開發者調用你的腳本檔案,又能輕松的在其他pc上運作。
最後提一下dos下的傳參指令,%0代表目前路徑,%1接收傳入的第一個參數,%2接收傳入的第二個參數……以此類推。%~dp0%和%0類似,代表目前路徑,但是與%0不同的是,%~dp0%可以擷取輸入路徑的父目錄,例輸入D:\codes\trunk\client\web\IBMS\webclient\build.bat,則%~dp0%=D:\codes\trunk\client\web\IBMS\webclient
好了,以上是這次研究的所有内容了,比較淺顯,有待深入研究!!!