Ant 是 Java 建構自動化的基石,IDE 內建建構往往掩蓋細節。本文實戰示範在 Eclipse 中手動配置 Ant 建構腳本,實現原始碼編譯、資源複製、單元測試、JAR/WAR 打包、API 文檔生成全流程自動化,打造 IDE 無關的標準化建構體系。
project-root/
├── src/ # Java 原始碼
├── classes/ # 編譯輸出
├── web/ # Web 資源 (JSP, HTML, CSS, JS, web.xml)
├── lib/ # 專案級相依 JAR (發布用)
├── dlist/ # 建構輸出 (JAR, WAR)
├── build.xml # Ant 建構腳本
└── build.properties # 環境變數外部化 (可選)
<property name="war.dir" value="dlist" />
<property name="src.dir" value="src" />
<property name="build.dir" value="classes" />
<property name="web.dir" value="web" />
<property name="lib.root" value="../common-lib" /> <!-- 外部共用庫根目錄 -->
<path id="master-classpath">
<fileset dir="${lib.root}/struts">
<include name="struts.jar" />
<include name="struts-menu-2.3.jar" />
</fileset>
<fileset dir="${lib.root}/jakarta-commons">
<include name="commons-*.jar" />
</fileset>
<fileset dir="${lib.root}/ibatis2.0.9">
<include name="ibatis-*.jar" />
</fileset>
<fileset dir="${lib.root}/jdbcdriver">
<include name="jtds-0.9-rc2.jar" />
</fileset>
<fileset dir="${lib.root}/spring-1.1.3">
<include name="spring.jar" />
<include name="aopalliance.jar" />
</fileset>
<pathelement path="${build.dir}" />
</path>
<target name="clean" description="Clean output directories">
<delete dir="${build.dir}" />
<delete dir="${war.dir}" />
<delete dir="${dlist.dir}" />
</target>
<target name="build" description="Compile sources, copy resources, build JAR">
<mkdir dir="${build.dir}" />
<!-- 編譯 Java 原始碼 -->
<javac srcdir="${src.dir}" destdir="${build.dir}"
source="1.3" target="1.3" debug="true" deprecation="false" optimize="false" failonerror="true">
<classpath refid="master-classpath" />
</javac>
<!-- 複製配置檔至 classes (打入 JAR) -->
<copy todir="${build.dir}" preservelastmodified="true">
<fileset dir="${src.dir}">
<include name="**/*.xml" />
<include name="**/*.properties" />
</fileset>
</copy>
<!-- Spring 資源檔特殊處理:複製至 WEB-INF/classes/conf (不打入 JAR) -->
<copy todir="${web.dir}/WEB-INF/classes/conf" preservelastmodified="true">
<fileset dir="${src.dir}/conf">
<include name="springResources*.properties" />
</fileset>
</copy>
<!-- 打包專案 JAR -->
<mkdir dir="${web.dir}/WEB-INF/lib" />
<jar jarfile="${web.dir}/WEB-INF/lib/${ant.project.name}.jar" compress="true">
<fileset dir="${build.dir}"><include name="**" /></fileset>
</jar>
<!-- 複製執行期相依 JAR 至 WEB-INF/lib -->
<copy todir="${web.dir}/WEB-INF/lib" preservelastmodified="true">
<fileset dir="${lib.root}"><include name="log4j-1.2.8.jar" /></fileset>
<fileset dir="${lib.root}/struts"><include name="struts*.jar" /></fileset>
<fileset dir="${lib.root}/jakarta-commons"><include name="commons-*.jar" /></fileset>
<fileset dir="${lib.root}/spring-1.1.3"><include name="spring.jar" /><include name="aopalliance.jar" /></fileset>
<!-- 其他相依... -->
</copy>
</target>
<target name="warfile" description="Build WAR archive">
<mkdir dir="${dlist.dir}" />
<war warfile="${dlist.dir}/${ant.project.name}.war"
basedir="${web.dir}"
webxml="${web.dir}/WEB-INF/web.xml">
<include name="*" />
<include name="WEB-INF/*.*" />
<exclude name="WEB-INF/web.xml" /> <!-- webxml 屬性已指定 -->
<include name="WEB-INF/classes/**" />
<include name="WEB-INF/lib/**" />
<exclude name="**/.*" /> <!-- 排除隱藏檔 -->
</war>
</target>
<target name="javadoc" description="Generate API documentation">
<mkdir dir="doc" />
<javadoc destdir="doc" author="true" version="true" use="true" windowtitle="Project API">
<packageset dir="${src.dir}" defaultexcludes="yes">
<include name="com/app/**" />
</packageset>
<doctitle><![CDATA[<h1>Project API Documentation</h1>]]></doctitle>
<bottom><![CDATA[<i>All Rights Reserved.</i>]]></bottom>
</javadoc>
</target>
<target name="all" description="Full build: clean → compile → war → javadoc">
<antcall target="clean" />
<antcall target="build" />
<antcall target="warfile" />
<antcall target="javadoc" />
</target>
<project name="MyWebApp" default="all" basedir=".">
<!-- 以上 targets 置於此處 -->
</project>
| 課題 | 解決方案 |
|---|---|
| 配置檔打包位置 | Struts/iBATIS/Spring XML 打入 JAR 正常;Spring `.properties` 資源檔需複製至 `WEB-INF/classes` 才能被 `ClassPathResource` 載入 |
| web.xml 位置 | 預先置於 `web/WEB-INF/web.xml`,`war` 任務 `webxml` 屬性指定 |
| TLD 檔案 | 預先置於 `web/WEB-INF/tld/` 或 `web/WEB-INF/`,隨 WAR 打包 |
| 相依管理 | 編譯期 Classpath (`master-classpath`) 與執行期 `WEB-INF/lib` 複製列表分離維護 |
| 跨 IDE 共用 | Ant 腳本無 IDE 綁定,Eclipse/JBuilder/IntelliJ 皆可執行 |
在 Eclipse 中手工打造 Ant 建構腳本,雖初期投入較大,但帶來三大核心價值:
掌握 Ant,是邁向 Maven/Gradle 等現代建構工具的必經內功,更是資深 Java 開發者區別於「IDE 依賴者」的關鍵分水嶺。