轉(zhuǎn)載自:https://www.cnblogs.com/pixy/p/4792887.html
Ant的由來(lái)(序)
James Duncan Davidson當(dāng)年用純Java開(kāi)發(fā)Tomcat的時(shí)候,不僅想讓它跨平臺(tái)運(yùn)行,還想要在不同的操作系統(tǒng)上都能夠進(jìn)行開(kāi)發(fā)和構(gòu)建。這種較大的項(xiàng)目的編譯構(gòu)建過(guò)程是很復(fù)雜胁塞,需要用到很多工具和腳本(比如GNU make荧关,Shell腳本护盈,批處理文件等等)處理資源、處理依賴項(xiàng)羞酗、控制編譯過(guò)程、打包(Jar紊服,War)檀轨,某些特別的Java技術(shù)如EJB、RMI在編譯打包時(shí)還需要特別處理欺嗤。James嘗試了很多工具和方案参萄,最后的結(jié)論就是太TM難用了。
首先是慢煎饼。舉個(gè)栗子讹挎,編譯java代碼要用javac,javac其實(shí)就是包裝了下java用于編譯的Java工具類(JDK工具都是用純Java寫(xiě)的吆玖,JDK目錄下的那些exe文件實(shí)際上都是調(diào)用Java類來(lái)實(shí)現(xiàn)具體功能的)筒溃。但是用make,shell這些工具每次調(diào)用javac沾乘,都要開(kāi)新進(jìn)程創(chuàng)建新的VM實(shí)例怜奖,如果每編譯一個(gè)文件調(diào)用一次javac,開(kāi)銷就老大了翅阵,不慢才怪呢歪玲。調(diào)用命令后還必須要解析控制臺(tái)輸出信息才能知道執(zhí)行情況,更不可能使用Java提供的異常和錯(cuò)誤信息來(lái)確定執(zhí)行狀態(tài)掷匠。
然后是累滥崩。make,shell腳本要跨平臺(tái)太困難讹语,在不同的系統(tǒng)上要用不同的版本钙皮;而且要編寫(xiě)shell腳本和make腳本(make只是shell基礎(chǔ)上的語(yǔ)言擴(kuò)展),得有l(wèi)inux編程基礎(chǔ)募强,門(mén)檻還是比較高的株灸;這類腳本編寫(xiě)起來(lái)容易出錯(cuò)(Makefile的tab問(wèn)題能煩死人),難以調(diào)試擎值』派眨總之,如果構(gòu)建過(guò)程用了一堆這樣的腳本鸠儿,維護(hù)起來(lái)肯定是又煩又累屹蚊。慢的問(wèn)題還能通過(guò)一次編譯一批文件來(lái)緩解厕氨,但這個(gè)問(wèn)題可就無(wú)解了。
James實(shí)在受不了了汹粤,就自己用Java開(kāi)發(fā)了一個(gè)小工具命斧,就是Ant,用來(lái)編譯和打包Java項(xiàng)目嘱兼。構(gòu)建中用到JDK中工具時(shí)都是直接調(diào)用Java類国葬,而不是從命令行調(diào)用,慢的問(wèn)題就解決了芹壕。構(gòu)建中直接向Java編譯類提供或獲取數(shù)據(jù)汇四,編譯過(guò)程中有什么問(wèn)題,也能進(jìn)行錯(cuò)誤或異常處理踢涌。因?yàn)槭怯肑ava寫(xiě)的通孽,天然就是可以跨平臺(tái)的使用的。Ant從配置文件中讀取數(shù)據(jù)來(lái)控制構(gòu)建過(guò)程睁壁,剛開(kāi)始的時(shí)候用Properties文件背苦,但是Properties文件難用表達(dá)比較復(fù)雜的層次結(jié)構(gòu)關(guān)系,當(dāng)他把Ant解決方案設(shè)計(jì)成"工程-目標(biāo)-任務(wù)"的層次結(jié)構(gòu)時(shí)潘明,改用XML作為構(gòu)建配置文件行剂,XML文件是很好理解和掌握的,學(xué)習(xí)門(mén)檻變得非常低钉疫。再后來(lái)又利用反射功能硼讽,支持自定義任務(wù),Ant的功能就不再僅限于構(gòu)建Java項(xiàng)目了牲阁,可以使用在更廣泛的場(chǎng)合固阁。至此Ant就基本成型了。
James完成這個(gè)工具之后城菊,自己用著很爽并且在網(wǎng)上共享备燃,然后就沒(méi)怎么再關(guān)注了,直到后來(lái)有一天忽然發(fā)現(xiàn)老多人都已經(jīng)在用他的這個(gè)杰作了凌唬。James說(shuō)他很慶幸當(dāng)時(shí)沒(méi)有把精力一直花在這上面并齐,否則可以能會(huì)不自覺(jué)的加入很多更本不必要的功能,讓Ant變得臃腫復(fù)雜客税,反而不好了况褪。
這個(gè)故事除了說(shuō)了Ant的來(lái)源和特點(diǎn)外,還有一點(diǎn)啟示:如果遇到問(wèn)題更耻,已有的工具都不能滿足需求测垛,就應(yīng)當(dāng)另找一個(gè)。如果不存在這樣的工具秧均,就自己動(dòng)手創(chuàng)建一個(gè)食侮。然后與大家共享号涯,其他數(shù)以千計(jì)的人可能有著類似的難題。
第一章 Ant入門(mén)
ant的使用非常簡(jiǎn)單:安裝好Ant后(最好配置Path環(huán)境變量)锯七,在構(gòu)建文件中(默認(rèn)名字為build.xml)配置好構(gòu)建任務(wù)链快,然后調(diào)用ant命令,配置的任務(wù)就開(kāi)始執(zhí)行了眉尸。
1.編寫(xiě)構(gòu)建文件
創(chuàng)建一個(gè)用于編譯和打包Java項(xiàng)目的配置文件build.xml(名字可以隨便起域蜗,如mybuild.xml,執(zhí)行的時(shí)候用-f 選項(xiàng)指定這個(gè)文件就可以):
這個(gè)配置文件很好理解噪猾,用任何文本編輯器都能編寫(xiě)地消,只要保證是一個(gè)合法的XML文件并且用了正確的標(biāo)簽和屬性,就可以使用ant運(yùn)行畏妖。
根據(jù)這個(gè)配置文件就可以看出。Ant把任何任務(wù)都分成了3層疼阔。
最頂層的Project
目標(biāo)Target(可以在ant命令中調(diào)用的基本單位)戒劫。如clean, compile, jar 等,在命令行可以這樣調(diào)用:ant clean或 ?ant clean jar婆廊。Target之間可以存在依賴關(guān)系迅细,一個(gè)Target執(zhí)行前會(huì)先執(zhí)行它依賴的那些Target。Project可以設(shè)置一個(gè)默認(rèn)的Targe淘邻, ant命令中不指定任何target時(shí)就調(diào)用這個(gè)默認(rèn)的茵典。
任務(wù)Task。
各種Task可以執(zhí)行各種不同的具體任務(wù)宾舅。如mkdir, delete, javac, jar等统阿。Task可以分3種,核心任務(wù)和可選任務(wù)有100多種筹我,常用的功能全都覆蓋了
核心Task扶平。Ant內(nèi)置的任務(wù)
可選任務(wù)。第三方提供的蔬蕊,把相應(yīng)的Jar包放到Ant安裝目錄的lib目錄下就能使用结澄。
自定義任務(wù)
Task詳細(xì)說(shuō)明可以查看官方文檔:http://ant.apache.org/manual/tasklist.html
Ant文件中還能用Property標(biāo)簽配置屬性值,在定義之后的其他地方就可以引用岸夯,避免硬編碼麻献。
所有的構(gòu)建文件都要有且只能有一個(gè)元素,其中至少要有一個(gè) 元素猜扮。project的defualt屬性沒(méi)有默認(rèn)值勉吻,如果這個(gè)屬性沒(méi)有設(shè)置,不指定Target運(yùn)行ant不會(huì)調(diào)用任何target破镰。
2.運(yùn)行Ant
ant命令語(yǔ)法如下餐曼,詳細(xì)選項(xiàng)說(shuō)明列在后面压储。
ant [option [option...]]? [target [target...]]
調(diào)用Ant時(shí)默認(rèn)會(huì)在當(dāng)前目錄中查找默認(rèn)的構(gòu)建文件名:build.xml。?
當(dāng)然也可以用ant -f buildfile的方式手動(dòng)指定構(gòu)建文件(-f, -buildfile, -file都是等效的)源譬。
調(diào)用Ant時(shí)可以指定一個(gè)或多個(gè)要執(zhí)行的Target集惋。如果不指定就調(diào)用Project標(biāo)簽default屬性中配置的默認(rèn)Target(上面這個(gè)例子中就是compile目標(biāo))。
以上面的構(gòu)建配置文件為例踩娘,下面的幾種調(diào)用都可以:
ant調(diào)用默認(rèn)構(gòu)建文件(build.xml)中的默認(rèn)目標(biāo)(compile)ant -f mybuild.xml? jar調(diào)用構(gòu)建文件mybuild.xml中的jar目標(biāo)ant clean jar調(diào)用默認(rèn)構(gòu)建文件(build.xml)中的clean和jar目標(biāo)刮刑。需要注意多個(gè)目標(biāo)會(huì)按調(diào)用先后順序執(zhí)行。如果調(diào)用ant jar clean就是先編譯打包(jar)养渴,然后全清理掉(clean)雷绢,就白干了。
Ant執(zhí)行時(shí)會(huì)按執(zhí)行順序顯示每個(gè)Target的名字理卑,也會(huì)顯示每個(gè)任務(wù)的名字([任務(wù)名])和任務(wù)中輸出的信息翘紊。直接調(diào)用ant的輸出結(jié)果為:
Buildfile: e:\wsJava\AntDemo\build.xml
clean:
? [delete] Deleting directory e:\wsJava\AntDemo\build
prepare:
? ? [mkdir] Createddir: e:\wsJava\AntDemo\build
? ? [mkdir] Createddir: e:\wsJava\AntDemo\build\classes
? ? [mkdir] Createddir: e:\wsJava\AntDemo\build\lib
compile:
? ? [javac] Compiling 2 sourcefilesto e:\wsJava\AntDemo\build\classes
jar:
? ? ? [jar] Building jar: e:\wsJava\AntDemo\build\lib\antDemo.jar
all:
BUILD SUCCESSFUL
Total time: 0 seconds
3.查看構(gòu)建文件中所有目標(biāo)
構(gòu)建文件中的目標(biāo)description屬性可有可無(wú),除了方便人看外沒(méi)什么卵用藐唠。有沒(méi)有這個(gè)屬性叫法也不一樣的(沒(méi)有實(shí)際作用)帆疟,有該屬性的叫主目標(biāo),沒(méi)有的叫子目標(biāo)宇立。下面這個(gè)命令可以列出構(gòu)建文件中的所有目標(biāo)和description信息踪宠。
ant [-f BUILDFILE] -projecthelp?
4.Ant命令選項(xiàng)
-h, ?-help ? 查看幫助信息
-p, ?-projecthelp ?查看構(gòu)建文件中的所有目標(biāo)信息
-version ?顯示Ant版本
-q, ?-quiet ? 抑制并非由構(gòu)建文件中echo任務(wù)所產(chǎn)生的大多數(shù)輸出消息
-S, ?-silent ? 只顯示Task輸出和構(gòu)建失敗信息
-v, ?-verbose ? 顯示構(gòu)建過(guò)程中每個(gè)操作的詳細(xì)消息, 不能和-debug同時(shí)使用
-d, ?-debug ? ? 顯示Ant和任務(wù)開(kāi)發(fā)人員已經(jīng)標(biāo)志位調(diào)試信息的消息妈嘹。不能與-verbose同時(shí)使用
-e, ?-emacs ? ? 對(duì)日志消息進(jìn)行格式化柳琢,使其能夠Emacs的shell模式解析。具體就是打印任務(wù)消息時(shí)不縮排也不輸出前面的 [任務(wù)名]
-diagnostics ? ?顯示對(duì)調(diào)試有用的信息
-f , ?-buildfile , -file 指定一個(gè)構(gòu)建文件润脸,而不是使用默認(rèn)的build.xml
-D=通過(guò)命令行向構(gòu)建過(guò)程中傳遞屬性值
-propertyfile 從property文件中加載屬性值并傳遞到構(gòu)建過(guò)程
-s , ?-find ? ? 指定Ant應(yīng)當(dāng)使用的構(gòu)建文件柬脸,如果指定的filename文件在當(dāng)前目錄中沒(méi)找到,就到父目錄中進(jìn)行搜索毙驯,直到到達(dá)文件系統(tǒng)的根肖粮,還找不到則構(gòu)建失敗。
-k, ?-keep-going ? ?執(zhí)行不依賴失敗目標(biāo)的所有目標(biāo)尔苦。
-lib ?指定查找jars和classes的目錄
-l ?, -logfile ? 將日志重定向到指定文件
-logger ? 指定一個(gè)類來(lái)處理Ant的日志記錄涩馆。該類必須實(shí)現(xiàn)了org.apache.tools.ant.BuildLogger接口
-listener ? 為Ant設(shè)置一個(gè)監(jiān)聽(tīng)類,將其增加到Ant的監(jiān)聽(tīng)器列表中允坚。Ant與IDE或其他程序集成時(shí)非常有用魂那,后面會(huì)專門(mén)寫(xiě)這個(gè)。
-inputhandler ?指定用于處理輸入請(qǐng)求的類
-main ? 覆蓋Ant正常的入口點(diǎn)
-noinput ? ?不允許交互式輸入
-autoproxy ? Java1.5+稠项,使用OS的代理設(shè)置
-nice number
-nouserlib
-noclasspath
第二章 安裝和配置
基本使用
下載ant發(fā)布包
解壓縮到一個(gè)目錄既可
將該目錄下的子目錄bin添加到PATH環(huán)境變量
高級(jí)配置
?留坑待填....
第三章 構(gòu)建文件
構(gòu)建文件需要根據(jù)具體項(xiàng)目的特性編寫(xiě)涯雅,不過(guò)同一類型的項(xiàng)目基本上是可以使用一套構(gòu)建配置的。
Java提供了用于構(gòu)建的Java工具庫(kù)展运,使用Java語(yǔ)言編寫(xiě)Ant是最容易實(shí)現(xiàn)和維護(hù)的活逆。XML有豐富的解析類庫(kù)精刷,并且被開(kāi)發(fā)人員廣泛使用,也能夠表達(dá)Ant的數(shù)據(jù)模型蔗候,使用XML作為構(gòu)建文件時(shí)最好的選擇怒允。
XML是一種樹(shù)形的文檔對(duì)象模型(DOM),其中的Project锈遥,Target等元素與Ant的模型組件相對(duì)應(yīng)纫事。
1.Ant的構(gòu)建塊
Project(工程) ??任何構(gòu)建文件的第一個(gè)元素必須是標(biāo)簽,而且只能有一個(gè)所灸。
name屬性?工程的名字丽惶,也是構(gòu)建文件的標(biāo)識(shí)符。
default屬性?運(yùn)行Ant不指定Target時(shí)爬立,默認(rèn)執(zhí)行的Target钾唬。可以設(shè)置成一個(gè)構(gòu)建文件中定義的Target名字侠驯。推薦默認(rèn)Target顯示構(gòu)建文件的幫助信息或者執(zhí)行完成的構(gòu)建知纷。
basedir屬性?定義工程的根目錄,一般情況下都是" . "陵霉,也就是構(gòu)建文件所在的目錄(不是運(yùn)行Ant命令是的目錄)。在一個(gè)多層次的項(xiàng)目中伍绳,basedir還可以定義不同的參考點(diǎn)踊挠。
Target(目標(biāo))?一個(gè)Project可以包含多個(gè)Target,一個(gè)總的任務(wù)過(guò)程可以拆分成幾個(gè)target冲杀,每個(gè)Target可以單獨(dú)調(diào)用效床。可以把target理解成能夠單獨(dú)執(zhí)行的一個(gè)個(gè)步驟(階段)权谁。具體怎么拆分這個(gè)總?cè)蝿?wù)剩檀,拆分粒度是粗還是細(xì),把哪些Task放在哪幾個(gè)Target中旺芽,都是編寫(xiě)構(gòu)建文件要考慮的問(wèn)題沪猴。一般來(lái)說(shuō),粒度更小可以更靈活的組合采章,有些target失敗也不會(huì)影響另一些的執(zhí)行运嗜。但是粒度也不能太小,太小了會(huì)很瑣碎不好維護(hù)悯舟。
name屬性
depends屬性
description屬性
前面的build.xml實(shí)例中担租,編譯打包拆成了兩個(gè)target,如果每次這兩個(gè)target都是一起被調(diào)用的抵怎,把他們放在一個(gè)target中也是可以的奋救。
Task(任務(wù)) ?任務(wù)是構(gòu)建文件中的最小構(gòu)建單位岭参。通過(guò)Target把一個(gè)總過(guò)程組織成了幾個(gè)大的Target目標(biāo)(步驟),但是Target并不做任何具體的工作尝艘,Target下面有包含一些Task演侯,所有的具體工作都是靠這些task來(lái)完成。Ant提供非常多的Task利耍,如編譯蚌本,大包,文件系統(tǒng)操作等等隘梨。Ant中每個(gè)任務(wù)對(duì)應(yīng)于Ant對(duì)象模型中的一個(gè)Java對(duì)象程癌,要自定義新的任務(wù)就是要編寫(xiě)執(zhí)行該任務(wù)類然后提供給Ant調(diào)用。很多系統(tǒng)命令也都是用Task包裝轴猎,而不是直接調(diào)用shell命令嵌莉,在不同的操作系統(tǒng)上Task的使用方式是完全一致的。
構(gòu)建文件中任務(wù)標(biāo)簽內(nèi)部也可以有很多層次捻脖。但是Task內(nèi)部的這些層次結(jié)構(gòu)和Java類的層次結(jié)構(gòu)沒(méi)有任何關(guān)系了锐峭。
Task標(biāo)簽不再有統(tǒng)一的屬性和子元素,內(nèi)部層次完全取決于具體的任務(wù)可婶。
2.數(shù)據(jù)元素(data element)
構(gòu)建文件中除了與任務(wù)構(gòu)建過(guò)程相關(guān)的元素外沿癞。還包括了保存數(shù)據(jù)的變量和抽象數(shù)據(jù)類型等元素。數(shù)據(jù)元素有兩類:Property和DataType
Property
表示字符串型的“鍵-值”對(duì)矛渴,只能用在可使用字符串的位置椎扬。
Propery和Java中的Property對(duì)象是兼容的娄涩,可以使用Property文件或JVM命令行-Dproperty=value選項(xiàng)钻蹬,在運(yùn)行ant時(shí)動(dòng)態(tài)定義起惕。
可以使用${propName}的形式引用Property數(shù)據(jù)复隆。
property數(shù)據(jù)定義和引用
加載config.properties文件中定義的property數(shù)據(jù)
通過(guò)命令行在運(yùn)行時(shí)動(dòng)態(tài)定義propery數(shù)據(jù)
ant mytarget -Dname=value
DataType
Property數(shù)據(jù)值都是字符串堪置,ant并不知道這些字符串代表了什么對(duì)象珊随。如果將包含很多個(gè)Jar文件的長(zhǎng)串路徑保存在Property數(shù)據(jù)中暑认,就很容易出錯(cuò)柏肪,修改也不方便达皿。
Ant還提供了很多種具體的數(shù)據(jù)類型(DataType)天吓,各種數(shù)據(jù)類型能夠更清晰地描述特定類型的數(shù)據(jù),如Path(路徑), FileSet(文件集合峦椰,可以使用通配符)等失仁,修改起來(lái)更加方便。
使用Property表示路徑和使用Path/FileSet對(duì)象表示路徑的對(duì)比:
3.工程結(jié)構(gòu)和構(gòu)建文件
要編寫(xiě)工程的構(gòu)建文件们何,必須要了解項(xiàng)目的結(jié)構(gòu)萄焦。項(xiàng)目類型不同,項(xiàng)目結(jié)構(gòu)往往存在較大的差異(如Web項(xiàng)目和GUI項(xiàng)目),沒(méi)有最佳的工程組織模式拂封。工程結(jié)構(gòu)是比較復(fù)雜的茬射,需要考慮跨平臺(tái)(使用相對(duì)路徑),依賴自包含無(wú)外部需求冒签,功能模塊和不同類型文件分離等等在抛。
以下面的項(xiàng)目結(jié)構(gòu)為例:
projectName
build.xml ? ? ?構(gòu)建文件
src/
api
module
doc/ ? ? ? 項(xiàng)目相關(guān)文檔(非JavaDoc文檔,不能自動(dòng)生成)萧恕,如readme刚梭,license等
lib/ ? ? ? ?依賴的外部庫(kù),統(tǒng)一依賴
bin/ 可選目錄票唆,包含安裝朴读、執(zhí)行等腳本或者是難找的、定制的可執(zhí)行工具(為跨平臺(tái)走趋,最好不要使用可執(zhí)行程序)
build/ ? ? 構(gòu)建產(chǎn)出目錄
classes/
doc/ ? javadoc產(chǎn)出
lib/ ? ?
bin/
dist/ ? ? 最終用于發(fā)布的目錄(內(nèi)容一般都是從其他目錄復(fù)制而來(lái))
lib/
bin/
doc/
config/
?編寫(xiě)構(gòu)建文件