Apache Ant 是基於 XML 的 Java 構建工具,雖然 Gradle/Maven 成為主流,但大量存量專案仍在使用。理解 Ant 核心概念(Target、Task、Property、Path、Fileset)有助於維護遺留構建、遷移至現代工具。
<?xml version="1.0" encoding="UTF-8"?>
<project name="tax-calculator" default="package" basedir=".>
<!-- 1. 目錄屬性 -->
<property name="src.dir" location="src"/>
<property name="build.dir" location="build"/>
<property name="test.dir" location="test"/>
<property name="build.classes.dir" location="${build.dir}/classes"/>
<property name="test.classes.dir" location="${build.dir}/test-classes"/>
<property name="lib.dir" location="lib"/>
<property name="dist.dir" location="dist"/>
<property name="report.dir" location="report"/>
<property name="report.xml.dir" location="${report.dir}/xml"/>
<property name="report.html.dir" location="${report.dir}/html"/>
<property name="report.javadoc.dir" location="${report.dir}/javadoc"/>
<!-- 2. 專案屬性 -->
<property name="project.name" value="${ant.project.name}"/>
<property name="project.version" value="1.0"/>
<!-- 3. 路徑定義 -->
<path id="compile.classpath">
<fileset dir="${lib.dir}" includes="*.jar"/>
</path>
<path id="test.compile.classpath">
<path refid="compile.classpath"/>
<pathelement location="${build.classes.dir}"/>
</path>
<path id="test.classpath">
<path refid="test.compile.classpath"/>
<pathelement location="${test.classes.dir}"/>
</path>
<!-- 4. 初始化:建立目錄 -->
<target name="init" description="Init directories">
<mkdir dir="${build.classes.dir}"/>
<mkdir dir="${test.classes.dir}"/>
<mkdir dir="${dist.dir}"/>
<mkdir dir="${test.dir}"/>
<mkdir dir="${lib.dir}"/>
<mkdir dir="${report.dir}"/>
<mkdir dir="${report.xml.dir}"/>
<mkdir dir="${report.html.dir}"/>
</target>
<!-- 5. 編譯主代碼 -->
<target name="compile" depends="init" description="Compile main sources">
<javac srcdir="${src.dir}" destdir="${build.classes.dir}"
classpathref="compile.classpath" includeantruntime="true"/>
</target>
<!-- 6. 編譯測試代碼 -->
<target name="compile-test" depends="compile" description="Compile test sources">
<javac srcdir="${test.dir}" destdir="${test.classes.dir}">
<classpath refid="test.compile.classpath"/>
</javac>
</target>
<!-- 7. 執行單元測試 -->
<target name="test" depends="compile-test" description="Run JUnit tests">
<junit printsummary="true" haltonfailure="false" failureproperty="test.failures">
<classpath refid="test.classpath"/>
<formatter type="plain" usefile="false"/>
<formatter type="xml"/>
<batchtest>
<fileset dir="${test.classes.dir}" includes="**/*Test.class"/>
</batchtest>
<!-- 也可指定單一測試類 -->
<test name="com.cn.hrbeu.ant.tax.test.TaxRateCalTest"/>
</junit>
</target>
<!-- 8. 生成測試報告 -->
<target name="test.report" depends="test" description="Generate HTML test report">
<junitreport todir="${report.xml.dir}">
<fileset dir="${report.xml.dir}" includes="TEST-*.xml"/>
<report format="frames" todir="${report.html.dir}"/>
</junitreport>
<fail if="test.failures" message="There were test failures."/>
</target>
<!-- 9. 生成 JavaDoc -->
<target name="javadoc" depends="init,compile" description="Generate JavaDoc">
<javadoc sourcepath="${src.dir}" destdir="${report.javadoc.dir}"
author="true" version="true" use="true" access="private"
linksource="true" windowtitle="${ant.project.name} API">
<classpath>
<path refid="compile.classpath"/>
<pathelement path="${build.classes.dir}"/>
</classpath>
<doctitle><![CDATA[<h1>${ant.project.name}</h1>]]></doctitle>
<bottom><![CDATA[<i>Copyright © 2007 All Rights Reserved</i>]]></bottom>
</javadoc>
</target>
<!-- 10. 打 JAR 包 -->
<target name="package" depends="compile" description="Generate JAR">
<tstamp>
<format property="build.date" pattern="EEEE, d MMMM YYYY"/>
<format property="build.time" pattern="hh:mm a"/>
</tstamp>
<jar destfile="${dist.dir}/${project.name}-${project.version}.jar"
basedir="${build.classes.dir}">
<fileset dir="${build.classes.dir}"/>
<fileset dir="${src.dir}"/> <!-- 包含源碼 -->
</jar>
</target>
<!-- 11. 打 WAR 包 -->
<target name="war" depends="compile" description="Generate WAR">
<war destfile="${dist.dir}/${project.name}-${project.version}.war"
basedir="${build.classes.dir}" webxml="">
<fileset dir="${build.classes.dir}"/>
<lib dir="${lib.dir}" includes="**.jar"/>
</war>
</target>
<!-- 12. 打 EAR 包 -->
<target name="ear" depends="compile" description="Generate EAR">
<ear destfile="${dist.dir}/${project.name}-${project.version}.ear" appxml=""></ear>
</target>
<!-- 13. 清理 -->
<target name="clean" description="Delete generated dirs">
<delete dir="${build.dir}"/>
<delete dir="${dist.dir}"/>
<delete dir="${report.dir}"/>
</target>
</project>
| 元素 | 作用 | 關鍵屬性/子元素 |
|---|---|---|
<property> | 定義不可變變數 | name, value/location/refid |
<path> | 定義類路徑/文件集合 | id, <pathelement>, <fileset>, <path refid> |
<fileset> | 文件模式匹配集合 | dir, includes/excludes, casesensitive |
<target> | 構建步驟單元 | name, depends, description, if/unless |
<javac> | 編譯 Java 源碼 | srcdir, destdir, classpathref, source/target, encoding |
<junit> | 運行 JUnit 測試 | printsummary, haltonfailure, failureproperty, <batchtest> |
<junitreport> | 生成 HTML 測試報告 | todir, <report format="frames"> |
<javadoc> | 生成 API 文檔 | sourcepath, destdir, access, linksource, <doctitle> |
<jar/war/ear> | 打包 | destfile, basedir, webxml/apppxml, <fileset>, <lib> |
<delete> | 刪除文件/目錄 | dir, file, includes/excludes |
<tstamp> | 生成時間戳屬性 | <format property pattern> |
<target name="foo" if="prop.set"> / unless="prop.not.set"<property file="build.properties"/> 覆蓋默認值<macrodef name="myjar"> 封裝可復用邏輯<parallel> 多目標並發(需線程安全)<if>/<for>/<trycatch> 等流程控制gradle init --type pom 或手寫 build.gradle 漸進遷移Ant 以 XML 聲明式構建,核心在於 **Property 不可變性**、**Path/Fileset 文件集合**、**Target 依賴鏈**。掌握上述範本涵蓋的編譯、測試、報告、打包、文檔、清理全生命周期,即可勝任絕大多數 Ant 維護工作。現代專案建議遷移至 Gradle/Maven 獲得更豐富的依賴管理、增量構建與插件生態。