這是以前學(xué)ANT時候做的筆記,本來想用《ANT學(xué)習(xí)筆記》做為標(biāo)題,發(fā)現(xiàn)已經(jīng)有人用了,我怕再用這個標(biāo)題別人會不高興的,干脆就叫《ANT從入門到提高》吧,確實(shí)也是我學(xué)習(xí)ANT時候一步步記錄下來的,整理了一下給放上來了,還在整理,很多地方需要修改和充實(shí)。
背景
關(guān)于ANT的起源,安裝和配置這些最基礎(chǔ)的知識我想沒有必要重復(fù)了,這方面的資源已經(jīng)很多了,最權(quán)威的莫過于官方站點(diǎn):http://ant.apache.org,還有一本好書推薦,就是Manning出版的Java Development With ANT。
中 文資料方面,現(xiàn)在網(wǎng)上比較好的中文資料是eric寫的《ant實(shí)踐》,大部分內(nèi)容來自官方站點(diǎn)上的使用手冊里面的Use ant這一章節(jié),當(dāng)初我學(xué)習(xí)ANT就是從看這篇文章開始的,建議學(xué)習(xí)ant可以從這篇文章起步。另外還有很多零散的ant的中文資料,感覺都沒有eric 寫的那篇好。呵呵,在此感謝eric,雖然我們并不認(rèn)識。
下面是我的學(xué)習(xí)筆記,這是我學(xué)習(xí)了eric的《ant實(shí)踐》之后然后開始看官方的使用手冊的時候總結(jié)的,主要是對我學(xué)習(xí)的時候感覺比較難掌握的地方的總結(jié)。
首先是一些在使用ant前應(yīng)該思考的問題,基本上這些問題的答案可以指導(dǎo)你怎么樣學(xué)好和用好ant
buildfile的結(jié)構(gòu)怎么樣的?
在build過程中我需要定義哪些property和datatype?
build過程中需要創(chuàng)建哪些目錄?
誰來負(fù)責(zé)一個完整的創(chuàng)建?還有庫文件,安裝和運(yùn)行的腳本文件,以及靜態(tài)的和生成的動態(tài)的文檔?
如果文件發(fā)生了變化,怎么重建?是否需要刪除所有的class文件?是否需要刪除生成的jar文件?
哪些目錄應(yīng)該在發(fā)布前準(zhǔn)備好?是否需要將源碼和應(yīng)用一起發(fā)布?誰負(fù)責(zé)發(fā)布?
內(nèi)容
一、ANT的安裝和配置(略,參考《ant實(shí)踐》吧)
二、ANT的學(xué)習(xí)方法
學(xué)
習(xí)ANT應(yīng)該從“到底要用ANT來做什么”開始,針對自己的目的來學(xué)習(xí),只要能夠滿足自己的工作的需要就可以了,ANT設(shè)計(jì)為可擴(kuò)展的插件式的結(jié)構(gòu),每天
都有人為ANT增加新的插件,因此要將ANT的所有功能掌握是不可能的,從我們的工作需求出發(fā),ANT主要就是用來compile, test,
build, package, deloy, integration
test,這也是我使用ANT的一種固定方式,我已經(jīng)為這個固定的方式寫了一個模板,每次編寫新的ANT的時候只需要針對具體的項(xiàng)目把這個模板修改一下就
可以了,其實(shí)使用ANT是很簡單的,如果ant很復(fù)雜和難于使用,相信也不會有如此的popular。
三、buildfile的結(jié)構(gòu)
對于ANT的使用者來說,理解ANT的配置文件是最重要的,ANT的XML配置文件的結(jié)構(gòu)很簡單,這也是ANT的一個優(yōu)點(diǎn),簡單易懂,容易上手,ANT的配置文件主要由project,target和task三層樹型結(jié)構(gòu)組成如下:
<project name="helloworld" default="master">
<property name="" value=""/>
<target name="master">
<task attribute1="" attribute2=""/><!--這是一個虛擬的task,具體到應(yīng)用可能是ant的core task也可能是optional task-->
</target>
</project>
關(guān)于project,target,task的概念,請參考官方文檔的6 Using Ant部分。
四、ANT的DataType
前
面說到了ANT的配置文件的結(jié)構(gòu)主要由project,target和task組成,其實(shí)project,target和task是ANT的四個重要的概
念里面的三個,還有一個很重要的概念就是Data
Elements(數(shù)據(jù)類型),這是ANT最容易讓人搞不清楚的一個方面,它們表達(dá)的是數(shù)據(jù)而不是任務(wù)。數(shù)據(jù)類型定義包括三個級別,project-
level,target-level和task-level,有點(diǎn)類似于類里面定義全局變量,局部變量的方式,不同的是,這里代表了其在ant
buildfile里面的可視性,如果直接定義在project節(jié)點(diǎn)下那就是project-level,所有的target和task都可以引用它們,
以次類推。
數(shù)據(jù)類型分為兩個部分:property和DataType。
property:<property/>標(biāo)簽里定義了name-value對。
DataType:用于表示一套復(fù)雜的數(shù)據(jù)集,例如FileSet和Path
數(shù)據(jù)類型的定義通常和target平級,也就是是數(shù)據(jù)類型一般直接在<project>下一層定義,當(dāng)然也有一些直接定義在task里面,通常我們定義的數(shù)據(jù)類型和target平級的時候,可以在task下面引用這些數(shù)據(jù)類型。
總結(jié)ANT的數(shù)據(jù)類型如下:
argument參數(shù):從命令行傳遞到buildfile的參數(shù)
environment環(huán)境變量:傳遞到buildfile的環(huán)境變量
filelist文件列表:文件不一定存在
fileset文件集:文件必須存在
patternset模式集
filterset過濾集
path路徑,還有classpath
mapper映射:定義了輸入與輸出文件之間的一套復(fù)雜的關(guān)系。
ANT的數(shù)據(jù)類型很多,以上列出的是一些常用的數(shù)據(jù)類型,下面重點(diǎn)總結(jié)一些我自己常用的數(shù)據(jù)類型,如environment,fileset,patternset,path
1、property屬性
一個項(xiàng)目可以配置很多property,property可以在在buildfile里面設(shè)置,也是可以在外部設(shè)置,在task中可以引用property,通過‘${‘和‘}‘符號來引用
除
了常見的在buildfile里面定義屬性外,很多情況下可以定義一個.properties文件,然后在buildfile里面load這個文件,這樣
的好處是可以讓buildfile不用修改的就在不同的環(huán)境里面運(yùn)行,用戶提供自己的.properties文件就可以了
例如,我們定義了一個build.properties文件
#build.properties
extend.1.dir =
extend.2.dir =
然后在buildfile里面load這個build.properties文件,在后面就可以直接引用該文件里定義的所有屬性了。
<property file="build.properties">
ANT屬性的定義原則是先定義的有效,也就是說相同的屬性,定義了多次,只有第一次定義的值是有效的,例如:
#override.properties
test=first
<!-- buildfile -->
<property file="override.properties"/>
<property name="test" value="second"/>
因?yàn)閛verride.properties文件中已經(jīng)設(shè)置了test的值,所以在buildfile里面第二次設(shè)置的值是無效的,test的值仍然是first
build-in properties
ANT提供了訪問系統(tǒng)properties的機(jī)制,也就是build-in properites,所謂系統(tǒng)properties,可以查看System.getProperties返回的值,以下是我的機(jī)器上的系統(tǒng)properties(只列出了一部分)
-- listing properties --
java.runtime.name=Java(TM) 2 Runtime Environment, Stand...
sun.boot.library.path=D:\jdk1.3.1_03\jre\bin
java.vm.version=1.3.1_03-b03
java.vm.vendor=Sun Microsystems Inc.
java.vendor.url=http://java.sun.com/
path.separator=;
java.vm.name=Java HotSpot(TM) Client VM
file.encoding.pkg=sun.io
java.vm.specification.name=Java Virtual Machine Specification
user.dir=G:\server
java.runtime.version=1.3.1_03-b03
java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironment
os.arch=x86
java.io.tmpdir=C:\TMP\
line.separator=
這些build-in properties可以直接象property那樣引用,例如:${java.home}
除此之外,ANT還提供了自身的build-in properties:
basedir
ant.file
ant.version
ant.project.name
ant.java.version
2、Environment環(huán)境變量
假設(shè)你根據(jù)你的工作環(huán)境配置了下面的property:
<property name="xalan.home" value="C:/java/xalan-j_2_1_0"/>
顯然你的buildfile到其他開發(fā)人員的環(huán)境下面還能繼續(xù)有效的可能性很小,因?yàn)槠渌说膞alan很可能在其他目錄,使用Environment環(huán)境變量可以解決這個問題
<property environment="env"/>
<property name="xalan.home" value="${env.XALAN_HOME}"/>
<target name="checkXalanHome" unless="env.XALAN_HOME">
<fail message="XALAN_HOME must be set!"/>
</target>
關(guān)鍵是:
<property environment="env"/>
設(shè)置了這個屬性之后,以后可以直接引用環(huán)境變量,只要前面加一個env.的前綴就可以了。
3、fileset文件集
fileset
表示了一套文件的集合,通常定義為project-level,ANT的task可以通過顯式(explicit)的方式來引用或者直接嵌套
fileset,如果是直接嵌套,這個時候fileset是task-level的,很多ANT的task都支持隱式(implicit)的
fileset,也就是說這些TASK支持fileset的所有屬性和嵌套的子元素,和filelist不同的是fileset所表示的文件必須存在。
Fileset可以定義為target-level的,并通過他們的id來引用。
fileset支持以下常用的屬性(只列出常用的,其他的請參考官方文檔):
attribute | description
----------------|------------------------------------------------
id |可選,定義了id將來就可以引用了
dir |必須指定,用于指定文件所在的目錄
excludes |可選,用于指定在dir指定的目錄下那些不應(yīng)該包括進(jìn)來的文件,內(nèi)容是逗號分割的文件模式(file pattern)。
excludesfile |跟excludes類似,區(qū)別是只能包括單獨(dú)的文件模式(不能用逗號分隔多個文件模式),通常情況下我習(xí)慣使用excludes,因?yàn)閑xcludes也包括了excludesfile的功能
includes |可選,用于指定在dir指定的目錄下那些需要包括進(jìn)來的文件,內(nèi)容是逗號分割的文件模式(file pattern)。
includesfile |跟includes類似,區(qū)別是只能包括單獨(dú)的文件模式(不能用逗號分隔多個文件模式),通常情況下我習(xí)慣使用includes,因?yàn)閕ncludes也包括了includesfile的功能
除了上面的屬性之外,fileset還可以嵌套多個(0...n)以下的patternset元素
<exclude> , <include> , <patternset> , <excludesfile> , <includesfile> .
關(guān)于patternset的用法,我會在patternset這個部分專門總結(jié)。
例子:
<fileset id="sources1" dir="src"
includes="**/*.java"
excludes="**/test/**/*.java">
</fileset>
等價于
<fileset id="sources2" dir="src">
<include name="**/*.java"/>
<exclude name="**/test/**/*.java"/>
</fileset>
等價于
<fileset id="sources3" dir="src">
<patternset>
<include name="**/*.java"/>
<exclude name="**/test/**/*.java"/>
</patternset>
</fileset>
也等價于
<patternset id="non.test.source">
<include name="**/*.java"/>
<exclude name="**/test/**/*.java"/>
</patternset>
<!-- later in the same buildfile -->
<fileset id="sources4" dir="src">
<patternset refid="non.test.source"/>
</fileset>
4、patternset模式集
fileset
將文件合成一個組,patternset將模式合成一個組,它們的概念很接近,其實(shí)fileset依賴于patternset來選擇文件,
patternset可以表達(dá)為target-level,然后通過它的id來引用,也可以直接嵌套在fileset下面,那些支持隱式
(implicit)的fileset的task也支持嵌套的patternset。
patternset支持includes, excludes, includesfile,excludesfile四個屬性,這跟fileset的用法一樣,還支持以下的嵌套的元素:
0..n 個嵌套的 <include>和<exclude>元素,它們支持以下屬性
attribute | description
----------------|------------------------------------------------
name |必須指定,內(nèi)容為相應(yīng)的include和exclude的模式。
if |可選,和target的if屬性的用法一樣
unless |可選,和target的unless屬性的用法一樣
0..n 個嵌套的 <includesfile> 和 <excludesfile> 元素,它們支持以下屬性:
attribute | description
----------------|------------------------------------------------
name |必須指定,內(nèi)容為相應(yīng)的include和exclude的模式,但是只能是單個
if |可選,和target的if屬性的用法一樣
unless |可選,和target的unless屬性的用法一樣
例子:
patternset的定義
<patternset id="xml.files">
<include name="**/*.dtd,**/*.xml,**/*.xslt"/>
</patternset>
patternset的引用
<fileset dir="${src.dir}">
<patternset refid="${xml.files}"/>
</fileset>
5、path路徑
path這個DataType除了單獨(dú)定義之外,還可以是某個元素的attribute也可以是這個元素下面一個嵌套的元素,最常用的是classpath這個形式,但是也用于其他用途。
當(dāng)作為XML元素使用的時候,path的用法非常的靈活,path支持以下attribute
attribute | description
----------------|------------------------------------------------
location |可選,表示單個文件或者單個路徑,它跟path的區(qū)別是數(shù)量上的,
|path可以表示多個文件和路徑
path |可選,路徑或者文件列表,用;或者:作為分隔符
refid |可選,引用其他的path的id,如果在buildfile里面會經(jīng)常用到同樣的path,
|可以將其定義為一個公用的,然后在使用到這個path的地方通過refid來引用,
|如果refid被指定了,path的其他attribute和其嵌套的元素都是禁止使用的。
path支持的嵌套元素如下:
0..n
個嵌套的<pathelement> pathlelement定義在路徑下的一個或者多個文件,
pathelement支持location和path這兩個attribute,用法和path元素一樣。(注意,他們之間可以互相嵌套,功能是非常強(qiáng)
大滴)
0..n 個嵌套的<fileset>
0..n 個嵌套的<path>
classpath是path元素的一個針對類路徑的特殊的元素,具有和path用樣的使用語法,但是使用的場合主要是<javac>task下面。
例子:
<classpath>
<pathelement path="${builddir}"/>
</classpath>
等價于
<classpath path="${builddir}"/>
<classpath>
<pathelement path="${builddir1}"/>
<pathelement path="${builddir2}"/>
</classpath>
等價于
<classpath path="${builddir1};${builddir2}"/>
<classpath>
<pathelement path="${builddir}"/>
<fileset dir="${libdir}" includes="**/*.jar"/>
</classpath>
<path>
<pathelement location="${libdir}/servlet.jar"/>
<pathelement location="${libdir}/logging.jar"/>
<pathelement path="${builddir}"/>
<pathelement path="${utilpath}"/>
</path>
五、目標(biāo)驅(qū)動的ANT
為
什么說目標(biāo)驅(qū)動ANT呢,這其實(shí)是我的學(xué)習(xí)方法,也就是說我使用ANT來做什么,而“做什么”就是我們的目標(biāo),也就是buildfile里面的
target,只學(xué)習(xí)跟我們的目標(biāo)有關(guān)的部分,其他的留到用的時候再去查閱有關(guān)資料,對于大部人來說,學(xué)習(xí)ANT的目的是為了更好的輔助項(xiàng)目的創(chuàng)建
(build),而不是要成為ANT的專家。
就我目前的工作內(nèi)容出發(fā),我需要ANT協(xié)助我完成編譯,測試,打包,發(fā)布,生成文檔,有些時候,還會使用到版本控制系統(tǒng)。
組織一個良好的目錄結(jié)構(gòu)是完成一次成功的build所必須的,apache的開源項(xiàng)目的目錄結(jié)構(gòu)提供了事實(shí)上(de facto)的標(biāo)準(zhǔn),如非特殊需要,我們可以直接采取那樣的目錄結(jié)構(gòu)。
project_home #項(xiàng)目所在目錄
\src #源碼
\java #Java主程序代碼
\test #Java測試程序代碼
\conf #manifest聲明文件
\lib #庫文件目錄
\doc #項(xiàng)目有關(guān)說明文檔,如果是開源項(xiàng)目,通常該目錄下是相應(yīng)的web content
\api #生成項(xiàng)目的Java API文檔的地方
\build #用于創(chuàng)建的臨時目錄
\classes #編譯的結(jié)果保存在該目錄
\dist #用于發(fā)布的臨時目錄,通常會將build\classes下的文件打包成jar,保存在該目錄下
README #項(xiàng)目的說明文件
RELEASE #項(xiàng)目的發(fā)布文件
LICENSE #項(xiàng)目的license文件
下面是一個和目錄有關(guān)的配置的例子:
<project name="helloworld" default="all" basedir=".">
<property name="src.dir" value="src"/>
<property name="lib.dir" value="lib"/>
<property name="build.dir" value="build"/>
<property name="dist.dir" value="dist"/>
<property name="doc.dir" value="doc"/>
<path id="compile.classpath">
<pathelement dir="${lib.dir}"/>
</path>
<path id="test.classpath">
<pathelement refid="compile.classpath"/>
<pathelement dir="${build.dir}/classes"/>
</path>
<!-- the following targets are ignored -->
</project>
編譯<javac>:
1。編譯器的選擇
對
于<javac>,除了classic(JDK 1.1/1.2)和modern(JDK
1.3/1.4/1.5),還有不同的編譯器可以選擇,例如:jikes,jvc,kjc,gcj,sj等等,不過我還沒有用過這些編譯器,<
javac>默認(rèn)的編譯器是你用來運(yùn)行ANT的JDK
1.X所帶的編譯器,如果你想使用自己的編譯器,需要如下聲明,ANT運(yùn)行<javac>的時候會自動用你配置的編譯器來編譯:
<property name="build.compiler" value="jikes"/><!-- 使用jikes編譯器 -->
2。<javac>的語法
編譯可以說是ANT里面最基本的任務(wù),首先回顧一下命令行下進(jìn)行編譯的命令:
c:\hellworld>javac -d build\classes
-classpath %CLASSPATH%;lib\outlib.jar
-sourcepath src
-g
下面是常用的<javac>語法列表,并附上對應(yīng)到j(luò)avac命令的參數(shù)
srcdir Java文件所在的目錄,相當(dāng)于javac命令的-sourcepath參數(shù),srcdir也是<javac>的隱式(implicit)的FileSet,因此srcdir支持FileSet的所有特征,有關(guān)FileSet的用法請參考前面。
destdir classes文件輸出的目錄,相當(dāng)于javac命令的-d參數(shù)
debug 生成并輸出調(diào)試信息,debug="yes"相當(dāng)于javac命令的-g參數(shù),debug="no"相當(dāng)于javac命令的-g:none參數(shù)
deprecation 輸出對于那些使用了deprecation的API的源文件的位置,默認(rèn)是off,deprecation="on"相當(dāng)于javac命令的-deprecation參數(shù)
optimize 優(yōu)化,默認(rèn)是off,optimize="on"相當(dāng)于javac命令的-o參數(shù)
fork 使用外部的JDK編譯器來運(yùn)行javac,默認(rèn)是no,采用yes可以取得更好的效率,當(dāng)然對機(jī)器的要求也高
failonerror 如果編譯錯誤,build是否繼續(xù),默認(rèn)是true
compiler 類似于全局的屬性build.compiler,不過這里是<javac>的attribute而已,直接指定<javac>的編譯器,用法和build.compiler一樣。
還有很多attribute,請參考官方文檔吧。
補(bǔ)充兩點(diǎn):
<javac>支持隱式的FileSet,支持<fileset>的所有attribute,不同的是dir在<javac>里面是srcdir。
<
javac>的srcdir, classpath, sourcepath, bootclasspath, 和extdirs
attributes都是path-like 結(jié)構(gòu),可以完全通過嵌套的 <src>, <classpath>,
<sourcepath>, <bootclasspath> and <extdirs> 元素來代替。
例子:
<javac destdir="${build.classes.dir}"
debug="${build.debug}"
includeAntRuntime="yes"
srcdir="${sirc.dir}">
<classpath refid="compile.classpath"/>
<include name="**/*.java"/>
</javac>
測試<junit>和<junitreport>:
JUnit是事實(shí)上(de facto)的Java單元測試工具,ANT集成了JUnit,可以在build過程中執(zhí)行test suite,并捕獲結(jié)果和生成報(bào)表,關(guān)于JUnit的用法,請查閱有關(guān)資料,這里只總結(jié)ANT怎么將JUnit集成到Build里面去的方法。
下面給出一些簡單的例子,先有個感性的認(rèn)識,后面在詳細(xì)講解一些常用的參數(shù),<junit>用法非常簡單,例如:
<junit>
<classpath refid="test.classpath"/>
<test name="myexample.Example1Test"/>
</junit>
為了捕獲測試結(jié)果,需要使用<format>,例如:
<junit printsummary="false" haltonfailure="true">
<classpath refid="test.classpath"/>
<formatter type="brief" usefile="false"/>
<test name="myexample.Example1Test"/>
</junit>
<junit>還支持運(yùn)行多個TestCase
<junit fork="yes">
<classpath refid="test.classpath"/>
<batchtest>
<fileset dir="${src.test.dir}">
<include name="**/*Test*.java"/>
<exclude name="**/AllTests.java"/>
</fileset>
</batchtest>
<junit>
下面講講junit支持的一些參數(shù)Parameters
attribute | description
----------------|------------------------------------------------
fork |在獨(dú)立的JVM里運(yùn)行測試,可以參考javac,java的fork屬性,默認(rèn)是off
haltonerror |測試的時候如果發(fā)生錯誤,是否停止整個build進(jìn)程,默認(rèn)是off
haltonfailure |測試的時候如果某個測試失敗了,是否停止整個build進(jìn)程,默認(rèn)是off
下面是JUnit支持的一些嵌套的元素Nested Elements
1。<classpath> 用法參考<path>部分
2。<test> 運(yùn)行單個TestCase
<test>支持以下參數(shù)Parameters
attribute | description
----------------|------------------------------------------------
name |測試的類的全名,必須指定
fork |在獨(dú)立的JVM里運(yùn)行測試,可以參考javac,java的fork屬性,默認(rèn)是off
haltonerror |測試的時候如果發(fā)生錯誤,是否停止整個build進(jìn)程,默認(rèn)是off
haltonfailure |測試的時候如果某個測試失敗了,是否停止整個build進(jìn)程,默認(rèn)是off
todir |測試結(jié)果的輸出目錄,默認(rèn)是當(dāng)前目錄
outfile |測試結(jié)果的輸出的文件名,默認(rèn)是TEST-name,全文件名取決于<formatter的定義>
注意,<test>支持if,unless參數(shù),還支持嵌套的<formatter>
3。<batchtest> 可運(yùn)行多個TestCase,并且支持<fileset>定義的所有TestCase
attribute | description
----------------|------------------------------------------------
fork |在獨(dú)立的JVM里運(yùn)行測試,可以參考javac,java的fork屬性,默認(rèn)是off
haltonerror |測試的時候如果發(fā)生錯誤,是否停止整個build進(jìn)程,默認(rèn)是off
haltonfailure |測試的時候如果某個測試失敗了,是否停止整個build進(jìn)程,默認(rèn)是off
todir |測試結(jié)果的輸出目錄,默認(rèn)是當(dāng)前目錄
注意,<batchtest>是批處理測試,因此不在支持具有單個測試含義的參數(shù),如name,outfile
4。<formatter>用來控制輸出結(jié)果的格式,支持下面的參數(shù)
attribute | description
----------------|------------------------------------------------
type |目前支持xml,plain,brief三種格式,plain和brief都是text格式,
|但是plain提供了更加詳細(xì)的統(tǒng)計(jì)信息
extension |輸出文件的擴(kuò)展名
usefile |輸出結(jié)果是否輸入到文件,默認(rèn)為true
注意,我們可以同時使用多次<formatter>,這樣可以控制多個輸出結(jié)果,例如
<formatter type="brief" usefile="false"/>
<formatter type="xml"/>
在控制臺顯示了測試結(jié)果的綜合信息,同時把詳細(xì)的測試結(jié)果寫入了XML文件
上面只列出了一些常用的參數(shù)和元素,再結(jié)合前面的例子應(yīng)該可以應(yīng)付基本的測試了。
<junitreport>的用法等待添加
發(fā)布
讓我們先看看發(fā)布前必須做的一些準(zhǔn)備工作:
1。撰寫文檔。
2。撰寫和平臺相關(guān)的自啟動腳本(bootstrap script),批處理文件(batch file) ,或者程序。
3。撰寫安裝腳本,使用安裝工具。
4。檢查版本控制系統(tǒng)中和項(xiàng)目相關(guān)的源碼,文檔,以及其他資料。
5。將版本控制系統(tǒng)中的源碼打上標(biāo)簽。
6。運(yùn)行一次完整的build。
7。運(yùn)行一次完整的測試。
8。將軟件打包成適當(dāng)?shù)男问?,用于發(fā)布和安裝。
對于打包這個步驟,如下圖
Data files Java source Documentation
| | |
| _____|_____ |
| | | |
| <javac> <javadoc> |
| | | |
|_____________| |__________________|
| |
jar |
| |
jar file |
|____________________________|
|
|
<zip><gzip><tar>
|
|
Distribution
package
將源碼和數(shù)據(jù)文件打包成JAR,將文檔和生成的文檔保存在某個目錄,然后將整體打包zip或者tar,為不同的平臺提供最終的版本以供下載,這就是打包的過程。
打包和發(fā)布的一個通用的過程是復(fù)制和移動文件的過程,在深入打包的細(xì)節(jié)之前,有必要總結(jié)一下ANT里面和復(fù)制,移動以及刪除有關(guān)的任務(wù)(這部分內(nèi)容大部分來自官方文檔,經(jīng)過翻譯和整理)。
<copy>
<copy>將文件或者FileSet復(fù)制到一個新的文件或者目錄。FileSet用于指定用于復(fù)制的文件集合,如果使用了FileSet,<copy>的todir必須指定一個值,<copy>支持的常用的attribute如下:
attribute | description
----------|------------------------------------------------
file | 要復(fù)制的文件
tofile | 復(fù)制到新的文件的文件名
todir | 復(fù)制到新的目錄的目錄名
overwrite | 默認(rèn)值為false,也就是只有當(dāng)被復(fù)制的文件比目標(biāo)文件新的時候才復(fù)制,
| 如果需要強(qiáng)制覆蓋目標(biāo)文件,需要將overwrite設(shè)置為true
<copy>嵌套<fileset>用于選擇用于復(fù)制的文件集合,這個時候需要指定todir
下面的例子均選自官方文檔
例一
<copy file="myfile.txt" tofile="mycopy.txt"/>
例二
<copy file="myfile.txt" todir="../some/other/dir"/>
例三
<copy todir="../new/dir">
<fileset dir="src_dir"/>
</copy>
例四
<copy todir="../dest/dir">
<fileset dir="src_dir">
<exclude name="**/*.java"/>
</fileset>
</copy>
例五
<copy todir="../dest/dir">
<fileset dir="src_dir" excludes="**/*.java"/>
</copy>
<move>
<move>跟<copy>的區(qū)別是移動而不是復(fù)制,語法跟<copy>一樣,這里不多寫了,只提供一些例子:
下面的例子均選自官方文檔
例一
<move file="file.orig" tofile="file.moved"/>
例二
<move file="file.orig" todir="dir/to/move/to"/>
例三
<move todir="new/dir/to/move/to">
<fileset dir="src/dir"/>
</move>
例四
<move todir="some/new/dir">
<fileset dir="my/src/dir">
<include name="**/*.jar"/>
<exclude name="**/ant.jar"/>
</fileset>
</move>
<delete>刪除單個文件,單個目錄,多個文件,多個目錄,支持FileSet,通常在清除build產(chǎn)生的臨時文件和目錄的時候會用到<delete>,一個典型的buildfile一般都會有一個名叫clean的target。
<delete>支持的最常見的attribute如下:
attribute | description
----------|------------------------------------------------
file | 指定文件,<delete file="somefile"/>
dir | 指定目錄,<delete dir="somedir"/>
可以嵌套<fileset>,但是如果沒有指定FileSet,file和dir其中之一必須指定。
下面的例子均選自官方文檔
例一
<delete file="/lib/ant.jar"/>
例二
<delete dir="lib"/>
例三
<delete>
<fileset dir="." includes="**/*.bak"/>
</delete>
例四
<delete includeEmptyDirs="true">
<fileset dir="build"/>
</delete>
例五
<delete includeemptydirs="true">
<fileset dir="build" includes="**/*"/>
</delete>
補(bǔ)充:關(guān)于復(fù)制,移動,刪除,還有一個重要的用法就是filter,不過我用到的機(jī)會不多,所以沒有怎么研究過,有關(guān)詳細(xì)的資料請查閱官方文檔。
發(fā)
布前還應(yīng)該準(zhǔn)備文檔,特別是javadoc文檔,<javadoc>是一個非常復(fù)雜的task,一共有50多個attribute,幸好只有
三個attribute是必須的,那就是sourcepath,sourcefiles,sourcepathref,destdir,對于
sourcepath,sourcefiles,sourcepathref只需要指定其中一個,如果都沒有指定,那么必須提供嵌套的<
sourcepath>, <fileset> 或者
<packageset>,從字面上很容易理解sourcepath,sourcefiles,sourcepathref是源文件所在的目
錄,而destdir是生成的javadoc API所在的目錄。
下面是一些我們常用的attribute,沒有必要去死記這些attribute,最好的學(xué)習(xí)方式是理解它們的意義,然后寫一個template,再用到的時候根據(jù)需要修改這個template就可以了:
attribute | description
----------------|------------------------------------------------
sourcepath |源文件目錄,可用嵌套的<sourcepath>代替
sourcefiles |逗號分割的文件列表,可用嵌套的<source>代替
destdir |輸出文件所在的目錄,通常我們習(xí)慣將結(jié)果保存在doc/api下
packagenames |逗號分割的java包列表,可用嵌套的<package>代替
packageList |指定一個文件,文件內(nèi)容是<javadoc>需要處理的包的列表
classpath |指定class文件所在的位置,可用嵌套的<classpath>代替
use |生成class和package的用法
version |生成@version的信息
author |生成@author的信息
windowtitle |生成的doc的瀏覽的窗口的標(biāo)題
header |每一頁的header信息
footer |每一頁的footer信息
bottom |每一頁的bottom信息
nodeprecated |不生成@deprecated的信息
常見的可以嵌套的參數(shù)如下:
packageset,fileset,package,excludepackage,source,doctitle,header,footer,bottom,它們的具體用法請參考官方文檔。
< javadoc>的sourcepath, classpath 和 bootclasspath是path-like機(jī)構(gòu),也就是完全可以用嵌套的<sourcepath>, <classpath> 和 <bootclasspath>來代替
給幾個例子:
例一
<javadoc packagenames="com.dummy.test.*"
sourcepath="src"
defaultexcludes="yes"
destdir="docs/api"
author="true"
version="true"
use="true"
windowtitle="Test API">
<classpath refid="compile.classpath"/>
</javadoc>
例二
<javadoc author="true"
destdir="${javadoc.dir}"
packagenames="org.example.helloworld.*"
sourcepath="src"
use="true"
version="true"
windowtitle="Helloworld api spec"
private="true">
<classpath refid="compile.classpath"/>
</javadoc>
例三
<javadoc
destdir="docs/api"
author="true"
version="true"
use="true"
windowtitle="Test API">
<packageset dir="src" defaultexcludes="yes">
<include name="com/dummy/test/**" />
<exclude name="com/dummy/test/doc-files/**"/>
</packageset>
<doctitle><![CDATA[<h1>Test</h1>]]></doctitle>
<bottom><![CDATA[<i>Copyright ? 2000 Dummy Corp. All Rights Reserved.</i>]]></bottom>
<tag name="todo" scope="all" description="To do:" />
<group title="Group 1 Packages" packages="com.dummy.test.a*"/>
<group title="Group 2 Packages" packages="com.dummy.test.b*:com.dummy.test.c*"/>
<link offline="true" href=" <link href=">
</javadoc>
準(zhǔn)備文檔的內(nèi)容除了javadoc之外,那些install script和其他document也是內(nèi)容之一,將其復(fù)制到待打包的目錄。
例如
<target name="prepare-docs" depends="init">
<property name="readme.file" location="readme.txt"/>
<copy file="${readme.file}" todir="${doc.dir}"/>
<copy file="${readme.file}" tofile="${doc.dir}/README"/>
</target>
因?yàn)閣indows平臺的文本文件行結(jié)束標(biāo)志為\r\n,而unix平臺的行結(jié)束標(biāo)志為\n,所以還要考慮平臺之間的純文本文件的格式問題,詳情請查閱有關(guān)資料。
接下來是準(zhǔn)備發(fā)布的庫文件,常見的庫文件的發(fā)布形式是打包之后的格式,如JAR,WAR,EAR,ZIP等等,
對
我來說最常用的是JAR,JAR文件是基于ZIP格式的,JAR文件本質(zhì)上就是ZIP文件,但是多了一個可選擇的META-INF目錄,JAR文件通常通
過命令行jar工具來創(chuàng)建,JAR文件不只是是java
class文件和resource文件簡單的進(jìn)行打包的結(jié)果,JAR文件是應(yīng)用程序創(chuàng)建的一個塊(block),而META-INF目錄,如果存在的話,
里面保存了包和擴(kuò)展的配置數(shù)據(jù),如安全,版本,擴(kuò)展和服務(wù)等等。在META-INF目錄下最常見的文件就是MANIFEST.MF,其他的文件請查閱
SUN關(guān)于JAR的規(guī)范。
下面重點(diǎn)講一下ANT的<jar>的用法,<jar>實(shí)際上就是將一些文件集合打包成JAR的
格式,這些文件打包成JAR之后,文件原來的permission,也就是訪問權(quán)限不會保留在JAR里面,同樣<jar>也支持隱式的
FileSet,basedir就是指定需要用于打包的文件所在的目錄,因?yàn)镴AR格式包含了manifest,如果沒有提供的話,ANT會自動提供一個
簡單的manifest文件,對于已經(jīng)存在的目標(biāo)文件,如果再次進(jìn)行打包,update參數(shù)可以控制是否覆蓋已經(jīng)存在的文件,下面是<
jar>支持的常見的attribute
attribute | description
----------------|------------------------------------------------
destfile |目標(biāo)文件,必須指定
basedir |用于打包的文件所在的目錄
compress |默認(rèn)為true,表示打包的同時還對文件進(jìn)行壓縮
manifest |指定要使用的manifest文件
update |默認(rèn)為false,該attribute用于指示jar在目標(biāo)文件
|已經(jīng)存在的情況下是否更新或者覆蓋目標(biāo)文件
支持的常見的嵌套的元素有manifest,fileset
關(guān)
于manifest的格式,一組name:value叫做section,section之間通過空行來隔開,manifest的配置文件就是由
section組成的,這里簡單列出META-INF/MANIFEST.MF文件里面常見的一些attribute:Manifest-
Version,Created-By,Main-Class,Specification-Title,Specification-Version,
Specification-Vendor,Implementation-Title,Implementation-Version
,Implementation-Vendor ,Sealed等等,至于這些attribute的解釋請查閱官方文檔。
大部分情況下,ANT自動生成的JAR的manifest已經(jīng)足夠了,如下:
Manifest-Version:1.0
Created-By:Apache Ant 1.5
但是如果你面臨以下情況的時候,需要自己提供manifest:
以下例子來自ANT官方手冊:
例一
<jar destfile="${dist}/lib/app.jar" basedir="${build}/classes"/>
${dist}/lib directory.
例二
<jar destfile="${dist}/lib/app.jar"
basedir="${build}/classes"
excludes="**/Test.class"
/>
${dist}/lib directory. Files with the name Test.class are excluded.
例三
<jar destfile="${dist}/lib/app.jar"
basedir="${build}/classes"
includes="mypackage/test/**"
excludes="**/Test.class"
/>
${dist}/lib directory. Only files under the directory mypackage/test are used, and files 例四
<jar destfile="${dist}/lib/app.jar">
<fileset dir="${build}/classes"
excludes="**/Test.class"
/>
<fileset dir="${src}/resources"/>
</jar>
例五
<jar destfile="test.jar" basedir=".">
<include name="build"/>
<manifest>
<attribute name="Built-By" value="${user.name}"/>
<section name="common/class1.class">
<attribute name="Sealed" value="false"/>
</section>
</manifest>
</jar>
關(guān)于manifest的用法請查閱官方手冊,這里給出例五創(chuàng)建的MANIFEST.MF文件的最后內(nèi)容:
Manifest-Version: 1.0
Built-By: conor
Created-By: Apache Ant 1.5alpha
Name: common/class1.class
Sealed: false
至于發(fā)布,其實(shí)通常很簡單,就是將打包的jar,war,ear文件復(fù)制到應(yīng)用服務(wù)器相應(yīng)的目錄下,只要掌握了<copy>就可以了。
七,高級特征
技
術(shù)每天都在發(fā)展,對于xdoclet,hibernate這樣非常優(yōu)秀的開源項(xiàng)目,我們有什么理由拒絕它們呢?不斷涌現(xiàn)的新的開源項(xiàng)目基本上都支持
ANT,因?yàn)锳NT設(shè)計(jì)為一個非常優(yōu)秀的插件式的可擴(kuò)展的結(jié)構(gòu),你所要做的就是學(xué)會使用<taskdef>,就可以適應(yīng)這個變化了。
等待添加中。。。。。。^_^