所有的語言都有維護和代碼重用的壓力,目前爲止,Ant已經提供了很多的Task,可以幫助實現Ant腳本的模塊化。
1. Property
Property Task除了能夠定義單個的屬性,還可以從一個屬性定義文件定義多個property。把公用的屬性放到屬性文件中,各個build.xml中都載入此屬性文件,就可以避免在每個build.xml中重複定義這些屬性。
2. AntCall, Ant和SubAnt
AntCall可以理解爲簡單的函數調用。舉一個例子就清楚了:
<target name=”commonTarget”>
<echo message=”${test.param}” />
</target>
<target name=”callingTarget”>
<antcall target="commonTarget">
<param name="test.param" value="Modulation" />
</antcall>
</target>
從上面的例子可以看到,指明要調用的target,再通過<param>指明調用參數;在被調用的Target中,通過與引用property類似的方式即可引用param的值。
至於Ant Target,也是調用別的Target,不過那個Target可以是在另外一個ant 文件中。
3. MacroDef
AntCall很好用,不過當參數很多時要寫很多的<param name=”” value=”” />起來很麻煩,如果你想偷懶,用MacroDef就行了。下面把上面的例子用MacroDef重寫:
<macrodef name="showModule">這裏是macrodef的定義
<attribute name="test.param1"/>這個是參數的定義,可以再macrodef外部調用
<attribute name="test.param" default="NOT SET"/>內部參數
<sequential>實際執行的內容都在sequential中
<echo message="@{test.param}" />
</sequential>
</macrodef>
<target name="testMacro">
<showModule test.param="Modulation" />
</target>
需要注意的是:
1,在整個build文件裏macrodef和target是平級的。
2,macrodef可以調用其他的macrodef,不可以調用target;target可以調用macrodef,也可以調用其他的target。
3,macrodef嵌套的時候,參數名稱必須不同。
我們可以象系統提供的其他Task一樣引用showModule,的確簡潔多了。定義一個Macro,首先定義此宏的attribute,包括attribute的name, default;然後在<sequential>標籤中定義此宏的所有操作。注意對attribute的引用是@{attr-name}!實際上,Ant還允許在attribute後面定義一組element,達到極高的動態性。
4. Import
<antcall>和<marcodef>可以達到類似函數的效果,但是調用者和被調用者還是必須在同一個文件中。Ant從1.6開始引入Import Task,可以真正的實現代碼重用:屬性,Task 定義,Task, Macro。一個簡單的例子:
common.xml:
<?xml version="1.0" ?>
<project>
<property name="project.name" value="Ant Modulazation" />
<target name="commonTarget">
<echo message="${test.param}" />
</target>
<macrodef name="showModule">
<attribute name="test.param" default="NOT SET"/>
<sequential>
<echo message="@{test.param}" />
</sequential>
</macrodef>
</project>
call.xml:
<?xml version="1.0" ?>
<project name="testCommon" default="callingTarget">
<import file="common.xml" />
<target name="callingTarget">
<antcall target="commonTarget">
<param name="test.param" value="Modulation" />
</antcall>
</target>
<target name="testMacro">
<showModule test.param="Modulation" />
</target>
</project>
注意:在common.xml中,不能對project元素設置屬性;另外,不要試圖使用重名的property,或target以獲取覆蓋的效果,因爲Ant畢竟不是編程語言。
自定義Ant Taskhttp://blog.csdn.net/pipisky2006/article/details/6680379
這裏只有task,也可以創建project對象,寫一個純code的build
1:基本環境,建議用Eclipse這個工具來做爲Java的基本開發工具,用Eclipse的嚮導新建一個Java工程test。
2:將ANT的以下幾個jar文件添加到剛纔新建的test工程的構建引用路徑下面,即添加到classpath中去:ant-lanucher.jar、ant.jar、ant-jakarta-log4j.jar這三個jar文件是最基本的,必須添加進去,如果要用到ANT的一些其它類,需要添加相應的jar文件,具體可以參考ANT的幫助文件。這三個文件簡單說明一下,ant-lanucher.jar裏面的類是ANT程序啓動時必須要用到的,在Java代碼中調ANT時,是需要通過這個包中的類來啓動ANT裏面的類去執行定義的動作,這個包是啓動入口類; ant.jar這個包裏面是ant定義的一些核心功能類的class,如copy文件,刪除文件,執行數據庫腳本,打包等等,即是具體的核心功能實現類,如果是一些附加的ant功能,則在其它jar包裏面,這個只有非常核心的類在裏面; ant-jakarta-log4j.jar是ant重新包裝了log4j的類,實現ANT自己格式的log4j的日誌文件記錄。
3:在test工程裏面新建一個類,類裏面增加一個Java的main方法,在main方法中添加如下代碼,並導入相關的package:
PrintStream logstream = null; //這裏是定義一個ANT執行時日誌文件的輸出流對象
Project pj=new Project(); //初始化一個ant的Project對象
pl.setName("ant_project"); //設置project的名稱,具體的值可以隨意改成其它字符串都可以
pj.init(); //ANT自己的方法初始化Project對象
DefaultLogger cl=new DefaultLogger();
//定義一個默認的日誌流,默認的日誌流是採用log4j來記錄的,所以在前面要求將ant-jakarta-log4j.jar這個文件加到classpath中去。
logstream=new PrintStream(new FileOutputStream("C:/test.log"),true);
//下面兩行是設置ANT執行過程中要輸出的一些信息流,必須設置,否則後面將得不到具體的日誌消息
cl.setErrorPrintStream(logstream);
cl.setOutputPrintStream(logstream);
//設置ANT記錄日誌的消息級別,MSG_VERBOSE是表示記錄詳細的日誌消息
cl.setMessageOutputLevel(Project.MSG_VERBOSE);
//將前面定義好的消息記錄器綁定到Project上
pj.addBuildListenter(cl);
//生成一個Target對象,爲後面添加具體的Task做準備
Target tg=new Target();
tg.setProject(pj); //設置target的Project歸屬,必須設置,Target必須屬於某一個Project
tg.setName("target1"); //設置Target的名稱
pj.addTarget(tg); //將Target添加到Project中
Copy cp=new Copy(); //具體生成一個功能Task類對象,複製文件的對象
cp.setTodir(new File("C:/bbb")); //設置要將文件複製的目的地
FileSet set=new FileSet(); //定義目錄集,這樣在後面可以自己定義一些規則
set.setDir(new File("C:/aaa")); //定義目錄集關聯的實際目錄路徑
set.createInclude().setName("**/*.txt"); //設置這個目錄集包括的規則,即這個目錄下面所有的.txt後綴的文件
cp.addFileset(set); //將目錄集綁定到具體的對象中
cp.setOverwrite(true);//設置在複製文件時,如果目標文件己經存在,將採用直接覆蓋的方式
cp.setFailOnError(true); //設置在複製文件過程中有文件複製失敗時,則中斷執行這個過程
cp.setPreserveLastModified(true); //設置複製文件時保留文件的最後修改時間
cp.setProject(pj); //設置Task的Project歸屬
cp.setTaskName("cp"); //設置Task的名稱
tg.addTask(cp); //將Task添加到Target中,Task不能單獨存在,也不能直接添加到Project中
Throwable ta=null;
try {
pj.executeTarget(tg.getName()); //開始執行Project中指定的Target
}catch (Exception e){
ta=e;
} finally {
/* 在日誌文件當中生成執行成功或失敗的消息,調用這個方法後,如果ANT的Project執行成功,則會在日誌文件當中生成一行“BUILD SUCCESSFUL”或"BUILD FAILED"這樣的字符串,在執行失敗時,同時會將異常消息打印在日誌文件中,所以這個方法比較重要 */
pj.fireBuildFinished(ta);
logstream.close();
}
(轉自: http://blog.csdn.net/pipisky2006/article/details/7101778)