1. Ant可以自动完成的任务:
(1)编译Java源代码;
(2)建立jar、war、zip文件;
(3)自动测试与生成报告;
(4)从CVS等管理系统取得源代码。
2. Ant相关网站:
Ant官方网站:http://ant.apachye.org/
Ant使用者手册:http://ant.apache.org/manual/index.html.
3. 第一个Ant构建:
Ant通过buildfile来进行构建,它是一个XML文件,默认命名为build.xml。
在Ant的buildfile中可以定义构建项目时的属性(Property)、任务(Task)。一个build.xml中可以定义多个任务,这些任务可能是建立目录、编译Java源代码、复制文件、删除文件、产生doc文件、进行测试、产生测试报告等,它们通常组织为一个目标(Target)。
这里以一个简单的HelloWorld程序来示范如何建立buildfile,并大致了解属性、任务与目标的作用。虽然HelloWorld程序使用Ant来构建过于夸张,但可以作为一个快速了解Ant的例子。先在D:\workspace\HelloWorld\src目录中编写文件:
package ysu.hxy;
public class HelloWorld
{
public static void main(String[] args)
{
System.out.println("Hello World!");
}
}
描述一下即将进行的工作。假设打算要编译src中的HelloWorld.java,编译后的.class将保存至C:\workspace\HelloWorld\classes目录中,如果classes目录不存在就建立它,每一次编译前将bin中前一次编译的.class复制到C:\workspace\HelloWorld\bak目录作备份,如果bak目录不存在就建立它,最后执行HelloWorld程序。在C:\workspace\HelloWorld下编辑build.xml如下:
<?xml version="1.0"?>
<project name="example" default="run">
<property name="src.dir" value="src"/>
<property name="classes.dir" value="classes"/>
<property name="bak.dir" value="bak"/>
<target name="prepare">
<mkdir dir="${classes.dir}"/>
<mkdir dir="${bak.dir}"/>
<copy todir="${bak.dir}">
<fileset dir="${classes.dir}"/>
</copy>
</target>
<target name="compile" depends="prepare">
<javac srcdir="${src.dir}" destdir="${classes.dir}"/>
</target>
<target name="run" depends="compile">
<java classname="ysu.hxy.HelloWorld">
<classpath path="${classes.dir}"/>
</java>
</target>
</project>
<project>中包括数个<target>,每个<target>有一个名称,默认<project>的进入点为run任务,而run任务的完成依赖于compile任务的完成,compile任务的完成依赖于prepare任务的完成。所以在构建开始时,会先执行prepare任务,完成后再执行compile任务,最后执行run任务。
<property>标签可以让您设定一些在构建项目时的常用属性值,每个属性值会有一个名称对应。对此例而言,设定了程序代码来源位置、编译结果的目标目录与备份目录。
一个构建中可以包括数个<target>,在此例中主要有3个<target>:编译前的准备工作、进行编译、执行。在编译之前先建立所需要的目录,如果目录已经存在就自动跳过该项工作,然后复制前一次编译的.class文件至bak目录。接下来进行编译,可以指定编译的源文件来源与目标,然后执行程序。
编辑好build.xml之后,在文字模式下直接执行ant指令即可开始构建项目,ant默认会读取同一个目录下的build.xml。第一次执行ant时会出现以下的文字提示构建过程。
D:\workspace\HelloWorld>ant
Buildfile: build.xml
prepare:
[mkdir] Created dir: D:\workspace\HelloWorld\classes
[mkdir] Created dir: D:\workspace\HelloWorld\bak
compile:
[javac] Compiling 1 source file to D:\workspace\HelloWorld\classes
run:
[java] Hello World!
BUILD SUCCESSFUL
Total time: 1 second
完成构建之后,会自动产生classes目录与bak目录。如果打算单独执行某个任务,则在执行ant指令时写出指定的任务名即可。例如:
D:\workspace\HelloWorld>ant compile
Buildfile: build.xml
prepare:
[copy] Copying 1 file to D:\workspace\HelloWorld\bak
compile:
[javac] Compiling 1 source file to D:\workspace\HelloWorld\classes
BUILD SUCCESSFUL
Total time: 1 second
4. 任务(Target):
在构建程序时,有些目标所定义的任务可能是可选的,您可以通过在设定<target>时设定一个条件,并在构建时指定该条件为true或false,以决定该目标是否要执行。例如可以这么设定:
<target name="someTarget" if="conditional"> some task... </target>
使用if设定条件目标时,表示只有在conditional被设置时才会被执行。在执行ant指令时,就可以像下面这样来决定someTarget是否要执行:
ant -buildfile build.xml -Dconditional=true
也可以使用unless来设定条件目标:
<target name="someTarget" unless="conditional">
some task...
</target>
由于使用了unless来设定条件目标,所以只有在confitional没有被设定时,目标才会被执行。
由于ant可以在一个buildfile中调用另一个buildfile,在调用的时候,两个buildfile之间可能会有一些重复的属性设定。如果要避免某个属性被重复设定了,可以这么编写:
<target name="setProperties" unless="setProperties"> <proporty name="someProperty" value="someValue"/> ... </target>
可以在一个buildfile中调用另一个buildfile。一个简单的例子如下:
<project name="someProject" default="all"> ... <target name="someTarget" depends="otherTarget"> <ant antfile="./project2/build.xml"> <property name="condition_name" value="true"/> </ant> </target> ... </project>
在<property>中设定value="true",当在另一个buildfile中有目标使用了条件式(if或unless)时,这可以给予该条件一个true的特性值。
由于默认的buildfile名称是build.xml,所以也可以只指定项目的目录来调用默认的build.xml,如下:
<project name="someProject" default="all"> ... <target name="someTarget" depends="otherTarget"> <ant antfile="./project2"> <property name="condition_name" value="true"/> </ant> </target> ... </project>
也可以仅仅调用另一个buildfile中的某个目标,如下:
<ant antfile="./project2/build.xml" target="prepare">
5. 属性(Property)
可以使用<property>标签来定义属性。例如:
<property name="src.dir" value="src"/> <property name="classes.dir" value="classes"/> <property name="bak.dir" value="bak"/>
属性都是由name/value组成的,如果在执行时没有特别指定属性值,则默认都是使用value上定义的值,如果要指定某个属性,则可以执行ant。例如指定classess.dir:
ant -Dclasses.dir="WEB-INF/classes"
也可以使用<property>取得环境变量,例如下面的buildfile尝试取得JAVA_HOME环境变量并显示它,如果没有设定这个环境变量,则会显示没有设定该环境变量的信息:
<?xml version="1.0"?>
<project name="envSample" default="deploy" basedir=".">
<!-- Set up the "env" prefix for environment variables-->
<property environment = "env"/>
<target name="checkJavaHome" unless="env.JAVA_HOME">
<fail message="JAVA_HOME must be set!"/>
</target>
......
</project>
也可以设定一个.properties文件,之后在buildfile指定运行ant时加载它。方法如下:
<property file="local.properties"/>
也可以通过ant执行buildfile时将指定的属性设定为系统环境变量。例如:
<sysproperty key="JAVA_HOME" value="${javaHome}"/>
还有一些方法可以取得系统属性。例如下面的方式可以取得使用者目录:
<echo message="user.home = ${user.home}"/>
6. 路径(Path)
使用Ant可以轻易地管理Classpath的设定问题。可以使用<path>来管理路径参考,使用<pathelement>来指定目录或jar文件。例如:
<path id="1">
<pathelement location="."/>
<pathelement location="./lib/junit.jar"/>
</path>
上面的例子也可以使用分号设定一系列的位置。例如:
<path id="1">
<pathelement location=".;./lib/junit.jar"/>
</path>
也可使用<fileset>来指定某个目录下的文件。例如:
<path id="2">
<fileset dir="lib">
<include name="**/*.jar"/>
</fileset>
</path>
<include>或<exclude>标签用来包括或排除文件(或是可以使用includes、excludes属性设定),可以在上面使用*表示零个或多个字符符合,?表示符合一个字符。
之后在进行<javac> 任务时,可以使用<classpath>标签像下面这样引用之前所设定的路径:
<javac srcdir="./src" destdir="./classes">
<classpath refid="1"/>
</javac>
也可以在进行<javac>任务时直接使用<pathelement>标签来指定Classpath。例如:
<javac srcdir="./src" destdir="./classes">
<classpath refid="1">
<pathelement location="."/>
<pathelement location="./lib/junit.jar"/>
</classpath>
</javac>
7.常用任务(Task)
(1)设定属性:
当在编写build.xml时发现到一些属性设定出现过两次以上,例如目录的指定,可以将这些属性使用<property>加以设定,以后若要改变属性设定,就只要改变对应的<property>即可,不必在build.xml中来回搜索与修改。例如:
<target name="setProperties">
<property name="src.dir" value="src"/>
<property name="classes.dir" value="classess"/>
<property name="lib.dir" value="lib"/>
<property name="backup.dir" value="bak"/>
<property name="jar.file" value="${lib.jar}/JNameIt.jar"/>
</target>
(2)提供help信息:
可以提供一些ant构建时的help信息。例如:
<target name="help" description="Type ant help for detail."> <echo message="Help information!!!"/> <echo>Help! Help!</echo> <echo><![CDATA[ Here is a help info. Write your own information here. ]]></echo> </target>
CDATA表示提供字符信息(Character Data),在![CDATA["与"]]之间的文字可以使用自由格式编写,适用于比较长的信息文字的显示。
在执行ant时加上-projecthelp或-p就会自动显示help这个<target>上的内容。如果<target>上加有description属性,当使用ant -projecthelp时也会一并显示该信息。一个执行的例子如下:
D:\workspace\HelloWorld>ant -p
Buildfile: build.xml
Main targets:
help Type ant help for detail.
Default target: run
要显示详细信息,则需运行ant时指定help这个<target>。下面介绍如何显示详细信息:
D:\workspace\HelloWorld>ant help
Buildfile: build.xml
help:
[echo] Help information!!!
[echo] Help! Help!
[echo]
[echo] Here is a help info.
[echo] Write your own information here.
[echo]
BUILD SUCCESSFUL
Total time: 0 seconds
(3)文件的复制、建立与删除:
在每次构建程序前,会备份前一次的构建结果,可以使用<copy>标签来指定要复制的文件。例如:
<target name="backup">
<copy todir="${backup.dir}">
<fileset dir="${classes.dir}"/>
</copy>
</target>
在构建程序时,可以使用<mkdir>标签建立一些必要的目录。例如:
<target name="prepareDir" description="prepare necessary dirs">
<mkdir dir="${classes.dir}"/>
<mkdir dir="${lib.dir}"/>
<mkdir dir="${backup.dir}"/>
</target>
(4)编译程序:
可以在编译程序时,加入一些Classpath的指定,这是一个相当方便的功能。例如:
<target name="compile" description ="Compile the source files">
<javac srcdir="./src" destdir="${classes.dir}">
<classpath>
<fileset dir="${lib.dir}">
<include name="**/*.jar"/>
</fileset>
</classpath>
</javac>
</target>
(5)执行程序:
<java>标签用来执行Java程序。例如:
<java classname="ysu.hxy.HelloWorld">
<classpath path="."/>
</java>
(6)制作jar文件:
可以使用<jar>标签将编译完成的文件打包为.jar文件(Java Archive File),并可以指定 MANIFEST文件,例如:
<target name="jar"> <mkdir dir="${libDir}"/> <jar jarfile="${libDir}/${jarFile}" manifest="META-INF/MANIFEST.MF" basedir="${lib.dir}"/> </target>
如果提供有MANIFEST.MF文件,才需要设定manifest属性。为了完成jar打包的任务,可以在META-INF目录下提供一个MANIFEST.MF文件。例如:
Manifest-Version: 1.0
Created-By: hxy
Main-Class: ysu.hxy.HelloWorld
Class-Path: HelloWorld.jar
此时build.xml文件如下:
<?xml version="1.0"?>
<project name="example" default="run">
<property name="src.dir" value="src"/>
<property name="classes.dir" value="classes"/>
<property name="bak.dir" value="bak"/>
<property name="lib.dir" value="lib"/>
<target name="help" description="Type ant help for detail.">
<echo message="Help information!!!"/>
<echo>Help! Help!</echo>
<echo><![CDATA[
Here is a help info.
Write your own information here.
]]></echo>
</target>
<target name="prepare">
<mkdir dir="${classes.dir}"/>
<mkdir dir="${bak.dir}"/>
<copy todir="${bak.dir}">
<fileset dir="${classes.dir}"/>
</copy>
</target>
<target name="compile" depends="prepare">
<javac srcdir="${src.dir}" destdir="${classes.dir}"/>
</target>
<target name="run" depends="compile">
<java classname="ysu.hxy.HelloWorld">
<classpath path="${classes.dir}"/>
</java>
</target>
<target name="jar">
<mkdir dir="${libDir}"/>
<jar jarfile="${libDir}/${jarFile}"
manifest="META-INF/MANIFEST.MF"
basedir="${classes.dir}"/>
</target>
</project>
执行ant时可以指定任务与提供lib目录及jar文件的名称。例如:
D:\workspace\HelloWorld>ant jar -DlibDir=lib -DjarFile=HelloWorld.jar
Buildfile: build.xml
jar:
[jar] Building jar: D:\workspace\HelloWorld\lib\HelloWorld.jar
BUILD SUCCESSFUL
Total time: 0 seconds
这里的设定所建立的jar由于包括Main-Class设定,而指定的类别中有main(),所以可以直接执行。例如:
D:\workspace\HelloWorld\lib>java -jar HelloWorld.jar
Hello World!
7. 制作War文件:
对于网站应用程序的部署,可以使用<war>标签将所有相关的文件包装为war(Web Application Archive)文件。例如:
<target name="war">
<war destfile="dist/guestbook.war"
webxml="src/webapp/WEB-INF/web.xml">
<classes dir="target/classes"/>
<lib file="beantools.jar"/>
</war>
</target>
8. 一个简单的buildfile,你可以根据实际需求来作修改。
<?xml version="1.0"?> <project name="example" default="run"> <property name="src.dir" value="src"/> <property name="classes.dir" value="classes"/> <property name="bak.dir" value="bak"/> <target name="help" description="Type ant help for detail."> <echo message="Help information!!"/> <echo>Usage:</echo> <echo><![CDATA[ build: ant ant build.xml produce jar: ant jar -DlibDir=lib -DjarFile=HelloWorld.jar You must produce META-INF/MANIFEST.MF. ex: ****************************************** Manifest-Version: 1.0 Created-By: caterpillar Main-Class: onlyfun.caterpillar.HelloWorld Class-Path: HelloWorld.jar ****************************************** ]]></echo> </target> <target name="jar"> <mkdir dir="${libDir}"/> <jar jarfile="${libDir}/${jarFile}" manifest="META-INF/MANIFEST.MF" basedir="${classes.dir}"/> </target> <target name="prepare"> <mkdir dir="${classes.dir}"/> <mkdir dir="${bak.dir}"/> <copy todir="${bak.dir}"> <fileset dir="${classes.dir}"/> </copy> </target> <target name="compile" depends="prepare"> <javac srcdir="${src.dir}" destdir="${classes.dir}"/> </target> <target name="run" depends="compile"> <java classname="ysu.hxy.HelloWorld"> <classpath path="${classes.dir}"/> </java> </target> </project>