Ant - 快速指南
ANT代表Another Neat Tool。 它是Apache的基于Java的构建工具。 在深入了解Apache Ant的细节之前,让我们先了解为什么我们首先需要构建工具。
需要构建工具
平均而言,开发人员花费大量时间执行构建和部署等普通任务,其中包括:
- 编译代码
- 打包二进制文件
- 将二进制文件部署到测试服务器
- 测试更改
- 将代码从一个位置复制到另一个位置
要自动化和简化上述任务,Apache Ant非常有用。 它是一个可以从命令行执行的操作系统构建和部署工具。
Apache Ant的历史
Ant由James Duncan Davidson(Tomcat的原作者)创建。
它最初用于构建Tomcat,并作为Tomcat发行版的一部分捆绑在一起。
Ant诞生于与Apache Make工具相关的问题和复杂性。
Ant于2000年被提升为Apache的独立项目。截至2014年5月,Apache Ant的最新版本为1.9.4。
Apache Ant的功能
Ant是最完整的Java构建和部署工具。
Ant是平台中立的,可以处理特定于平台的属性,例如文件分隔符。
Ant可用于执行特定于平台的任务,例如使用“touch”命令修改文件的修改时间。
Ant脚本使用纯XML编写。 如果您已经熟悉XML,则可以快速学习Ant。
Ant善于自动执行复杂的重复性任务。
Ant附带了大量预定义任务。
Ant提供了一个开发自定义任务的界面。
可以从命令行轻松调用Ant,它可以与免费和商业IDE集成。
Ant - Environment Setup
Apache Ant Ant是在Apache软件许可下发布的,这是一个由开源计划认证的完全开源的许可证。
最新的Apache Ant版本,包括其完整源代码,类文件和文档,可以在http://ant.apache.org.找到http://ant.apache.org.
安装Apache Ant
假设您已经在计算机上下载并安装了Java Development Kit(JDK)。 如果没有,请按照here的说明操作。
确保将JAVA_HOME环境变量设置为安装JDK的文件夹。
从http://ant.apache.org下载二进制文件
将zip文件解压缩到方便的位置c:\文件夹。 使用Winzip,winRAR,7-zip或类似工具。
创建一个名为ANT_HOME的新环境变量,该变量指向Ant安装文件夹,在本例中为c:\apache-ant-1.8.2-bin文件夹。
将Apache Ant批处理文件的路径附加到PATH环境变量。 在我们的例子中,这将是c:\apache-ant-1.8.2-bin\bin文件夹。
验证Apache Ant安装
要验证在计算机上成功安装Apache Ant,请在命令提示符下键入ant。
您应该看到类似于的输出:
C:\>ant -version
Apache Ant(TM) version 1.8.2 compiled on December 20 2010
如果您没有看到上述输出,请确认您已正确执行安装步骤。
安装Eclipse
本教程还介绍了Ant与Eclipse IDE的集成。 因此,如果您尚未安装Eclipse,请下载并安装Eclipse
要安装Eclipse:
从www.eclipse.org下载最新的Eclipse二进制文件
将Eclipse二进制文件解压缩到一个方便的位置,例如c:\folder
从c:\eclipse\eclipse.exe运行Eclipse
Ant - Build Files
通常,Ant的构建文件(称为build.xml应驻留在项目的基本目录中。 但是,文件名或其位置没有限制。 您可以自由使用其他文件名或将构建文件保存在其他位置。
在本练习中,在计算机的任何位置创建一个名为build.xml的文件,其中包含以下内容:
<?xml version="1.0"?>
<project name="Hello World Project" default="info">
<target name="info">
<echo>Hello World - Welcome to Apache Ant!</echo>
</target>
</project>
请注意,在xml声明之前不应有空行或空格。 如果您允许它们,执行ant构建时会出现以下错误消息 -
The processing instruction target matching "[xX][mM][lL]" is not allowed. 所有构建文件都需要project元素和至少一个target元素。
XML元素project有三个属性:
属性 | 描述 |
---|---|
name | 项目名称。 (可选的) |
default | 构建脚本的默认目标。 项目可能包含任意数量的目标。 此属性指定应将哪个目标视为默认目标。 (必须) |
basedir | 基本目录(或)项目的根文件夹。 (可选的) |
目标是您希望作为一个单元运行的任务集合。 在我们的示例中,我们有一个简单的目标来向用户提供信息性消息。
目标可以依赖于其他目标。 例如, deploy目标可能具有对package目标的依赖性, package目标可能具有对compile目标的依赖性等等。 依赖关系使用depends属性表示。 例如:
<target name="deploy" depends="package">
....
</target>
<target name="package" depends="clean,compile">
....
</target>
<target name="clean" >
....
</target>
<target name="compile" >
....
</target>
target元素具有以下属性:
属性 | 描述 |
---|---|
name | 目标名称(必填) |
depends | 以逗号分隔的目标所依赖的所有目标的列表。 (可选的) |
description | 目标的简短描述。 (可选的) |
if | 允许基于条件属性的真实性执行目标。 (可选的) |
unless | 将目标添加到指定Extension Point的依赖项列表中。 扩展点类似于目标,但它没有任何任务。 (可选的) |
上例中的echo任务是一个打印消息的简单任务。 在我们的示例中,它打印消息Hello World 。
要运行ant构建文件,请打开命令提示符并导航到build.xml所在的文件夹,然后键入ant info 。 你也可以输入ant 。 两者都可以,因为info是构建文件中的默认目标。 您应该看到以下输出:
C:\>ant
Buildfile: C:\build.xml
info: [echo] Hello World - Welcome to Apache Ant!
BUILD SUCCESSFUL
Total time: 0 seconds
C:\>
Ant - Property Task
Ant构建文件是用XML编写的,它不允许像你喜欢的编程语言那样声明变量。 但是,正如您可能想象的那样,如果Ant允许声明项目名称,项目源目录等变量,那将非常有用。
Ant使用property元素,允许您指定属性。 这允许将属性从一个构建更改为另一个或从一个环境更改为另一个。
默认情况下,Ant提供以下可在构建文件中使用的预定义属性:
属性 | 描述 |
---|---|
ant.file | 构建文件的完整位置。 |
ant.version | Apache Ant安装的版本。 |
basedir | 构建的基础,在project元素的basedir属性中指定。 |
ant.java.version | Ant使用的JDK版本。 |
ant.project.name | 项目name ,在project元素的name atrribute中指定。 |
ant.project.default-target | 当前项目的默认目标。 |
ant.project.invoked-targets | 以逗号分隔的当前项目中调用的目标列表。 |
ant.core.lib | Ant jar文件的完整位置。 |
ant.home | Ant安装的主目录。 |
ant.library.dir | Ant库文件的主目录 - 通常是ANT_HOME/lib文件夹。 |
Ant还使构建文件可以使用系统属性(示例:file.separator)。
除上述内容外,用户还可以使用property元素定义其他属性。 以下示例显示如何定义名为sitename的属性:
<?xml version="1.0"?>
<project name="Hello World Project" default="info">
<property name="sitename" value="www.iowiki.com"/>
<target name="info">
<echo>Apache Ant version is ${ant.version} - You are
at ${sitename} </echo>
</target>
</project>
在上面的构建文件上运行Ant会产生以下输出:
C:\>ant
Buildfile: C:\build.xml
info: [echo] Apache Ant version is Apache Ant(TM) version 1.8.2
compiled on December 20 2010 - You are at www.iowiki.com
BUILD SUCCESSFUL
Total time: 0 seconds
C:\>
Ant - Property Files
如果您正在使用一些属性,则直接在构建文件中设置属性是可以的。 但是,对于大型项目,将属性存储在单独的属性文件中是有意义的。
将属性存储在单独的文件中具有以下优点:
它允许您重用相同的构建文件,并为不同的执行环境使用不同的属性设置。 例如,可以为DEV,TEST和PROD环境单独维护构建属性文件。
当您事先不知道属性(在特定环境中)的值时,它很有用。 这允许您在已知属性值的其他环境中执行构建。
没有硬性规则,但通常属性文件名为build.properties并且与build.xml文件并排放置。 您可以基于部署环境创建多个构建属性文件 - 例如build.properties.dev和build.properties.test.
build属性文件的内容类似于普通的java属性文件。 它们每行包含一个属性。 每个属性由名称和值对表示。 名称和值对由等号(=)分隔。 强烈建议使用适当的注释对属性进行注释。 使用散列(#)字符列出注释。
以下示例显示了build.xml文件及其关联的build.properties文件:
build.xml
<?xml version="1.0"?>
<project name="Hello World Project" default="info">
<property file="build.properties"/>
<target name="info">
<echo>Apache Ant version is ${ant.version} - You are
at ${sitename} </echo>
</target>
</project>
build.properties
# The Site Name
sitename=www.iowiki.com
buildversion=3.3.2
在上面的示例中, sitename是一个自定义属性,映射到网站名称。 您可以以这种方式声明任意数量的自定义属性。 上面示例中列出的另一个自定义属性是buildversion ,在本例中,它指的是构建版本。
除了上述内容之外,Ant还提供了许多预定义的构建属性,这些属性在上一节中列出,但在下面再次表示。
属性 | 描述 |
---|---|
ant.file | 构建文件的完整位置。 |
ant.version | Apache Ant安装的版本。 |
basedir | 构建的基础,在project元素的basedir属性中指定。 |
ant.java.version | Ant使用的JDK版本。 |
ant.project.name | 项目name ,在project元素的name atrribute中指定。 |
ant.project.default-target | 当前项目的默认目标。 |
ant.project.invoked-targets | 以逗号分隔的当前项目中调用的目标列表。 |
ant.core.lib | Ant jar文件的完整位置。 |
ant.home | Ant安装的主目录。 |
ant.library.dir | Ant库文件的主目录 - 通常是ANT_HOME/lib文件夹。 |
本章介绍的示例使用ant.version内置属性。
Ant - Data Types
Ant提供了许多预定义的数据类型。 不要将术语“数据类型”与编程语言中可用的术语混淆,而应将它们视为已经内置到产品中的一组服务。
Apache Ant提供以下数据类型。
Fileset
文件集数据类型表示文件的集合。 它用作过滤器以包含或排除与特定模式匹配的文件。
例如,请参阅以下代码。 这里,src属性指向项目的源文件夹。
文件集选择源文件夹中的所有.java文件,但包含单词“Stub”的文件除外。 区分大小写的过滤器应用于文件集,这意味着不会从文件集中排除名为Samplestub.java的文件。
<fileset dir="${src}" casesensitive="yes">
<include name="**/*.java"/>
<exclude name="**/*Stub*"/>
</fileset>
模式集
模式集是一种允许根据特定模式轻松过滤文件或文件夹的模式。 可以使用以下元字符创建模式:
? - 仅匹配一个角色。
* - 匹配零个或多个字符。
** - 递归匹配零个或多个目录。
以下示例描述了模式集的用法。
<patternset id="java.files.without.stubs">
<include name="src/**/*.java"/>
<exclude name="src/**/*Stub*"/>
</patternset>
然后可以使用文件集重用模式集,如下所示:
<fileset dir="${src}" casesensitive="yes">
<patternset refid="java.files.without.stubs"/>
</fileset>
文件列表
文件列表数据类型与文件集类似,但以下区别除外:
filelist包含明确命名的文件列表,它不支持通配符。
文件列表数据类型可以应用于现有或不存在的文件。
让我们看一下filelist数据类型的以下示例。 这里,属性webapp.src.folder指向项目的Web应用程序源文件夹。
<filelist id="config.files" dir="${webapp.src.folder}">
<file name="applicationConfig.xml"/>
<file name="faces-config.xml"/>
<file name="web.xml"/>
<file name="portlet.xml"/>
</filelist>
过滤器组
使用filterset数据类型以及复制任务,可以将与模式匹配的所有文件中的某些文本替换为替换值。
一个常见示例是将版本号附加到发行说明文件中,如以下代码所示。
<copy todir="${output.dir}">
<fileset dir="${releasenotes.dir}" includes="**/*.txt"/>
<filterset>
<filter token="VERSION" value="${current.version}"/>
</filterset>
</copy>
在本守则中:
output.dir属性指向项目的输出文件夹。
属性releasenotes.dir指向项目的发行说明文件夹。
current.version属性指向项目的当前版本文件夹。
顾名思义,复制任务用于将文件从一个位置复制到另一个位置。
Path
path数据类型通常用于表示类路径。 路径中的条目使用分号或冒号分隔。 但是,这些字符在运行时由执行系统的路径分隔符替换。
类路径设置为项目中jar文件和类的列表,如下例所示。
<path id="build.classpath.jar">
<pathelement path="${env.J2EE_HOME}/${j2ee.jar}"/>
<fileset dir="lib">
<include name="**/*.jar"/>
</fileset>
</path>
在这段代码中:
属性env.J2EE_HOME指向环境变量J2EE_HOME 。
属性j2ee.jar指向J2EE基本文件夹中的J2EE jar文件的名称。
Ant - Building Projects
现在我们已经了解了Ant中的数据类型,现在是时候将这些知识付诸实践了。 我们将在本章中构建一个项目。 本章的目的是构建一个Ant文件,该文件编译java类并将它们放在WEB-INF\classes文件夹中。
考虑以下项目结构:
数据库脚本存储在db文件夹中。
java源代码存储在src文件夹中。
图像,js,META-INF,样式(css)存储在war文件夹中。
JSP存储在jsp文件夹中。
第三方jar文件存储在lib文件夹中。
java类文件存储在WEB-INF\classes文件夹中。
此项目构成本教程其余部分的Hello World传真应用程序。
C:\work\FaxWebApplication>tree
Folder PATH listing
Volume serial number is 00740061 EC1C:ADB1
C:.
+---db
+---src
. +---faxapp
. +---dao
. +---entity
. +---util
. +---web
+---war
+---images
+---js
+---META-INF
+---styles
+---WEB-INF
+---classes
+---jsp
+---lib
这是此项目所需的build.xml。 让我们一块一块地考虑它。
<?xml version="1.0"?>
<project name="fax" basedir="." default="build">
<property name="src.dir" value="src"/>
<property name="web.dir" value="war"/>
<property name="build.dir" value="${web.dir}/WEB-INF/classes"/>
<property name="name" value="fax"/>
<path id="master-classpath">
<fileset dir="${web.dir}/WEB-INF/lib">
<include name="*.jar"/>
</fileset>
<pathelement path="${build.dir}"/>
</path>
<target name="build" description="Compile source tree java files">
<mkdir dir="${build.dir}"/>
<javac destdir="${build.dir}" source="1.5" target="1.5">
<src path="${src.dir}"/>
<classpath refid="master-classpath"/>
</javac>
</target>
<target name="clean" description="Clean output directories">
<delete>
<fileset dir="${build.dir}">
<include name="**/*.class"/>
</fileset>
</delete>
</target>
</project>
首先,让我们声明源,Web和构建文件夹的一些属性。
<property name="src.dir" value="src"/>
<property name="web.dir" value="war"/>
<property name="build.dir" value="${web.dir}/WEB-INF/classes"/>
在这个例子中:
src.dir指的是可以找到java源文件的项目的源文件夹。
web.dir是指项目的Web源文件夹,您可以在其中找到JSP,web.xml,css,javascript和其他Web相关文件
build.dir是指项目编译的输出文件夹。
属性可以引用其他属性。 如上例所示, build.dir属性引用web.dir属性。
在此示例中, src.dir引用项目的源文件夹。
我们项目的默认目标是compile目标。 但首先让我们看看clean目标。
清楚的目标,顾名思义,删除build文件夹中的文件。
<target name="clean" description="Clean output directories">
<delete>
<fileset dir="${build.dir}">
<include name="**/*.class"/>
</fileset>
</delete>
</target>
master-classpath保存类路径信息。 在这种情况下,它包括build文件夹中的类和lib文件夹中的jar文件。
<path id="master-classpath">
<fileset dir="${web.dir}/WEB-INF/lib">
<include name="*.jar"/>
</fileset>
<pathelement path="${build.dir}"/>
</path>
最后,构建目标来构建文件。 首先,我们创建构建目录(如果它不存在)。 然后我们执行javac命令(将jdk1.5指定为目标编译)。 我们为javac任务提供源文件夹和类路径,并要求它将类文件放在build文件夹中。
<target name="build" description="Compile main source tree java files">
<mkdir dir="${build.dir}"/>
<javac destdir="${build.dir}" source="1.5" target="1.5" debug="true"
deprecation="false" optimize="false" failonerror="true">
<src path="${src.dir}"/>
<classpath refid="master-classpath"/>
</javac>
</target>
在此文件上执行Ant会编译java源文件并将类放在build文件夹中。
以下结果是运行Ant文件的结果:
C:\>ant
Buildfile: C:\build.xml
BUILD SUCCESSFUL
Total time: 6.3 seconds
这些文件被编译并放在build.dir文件夹中。
Ant - Build Documentation
文档是任何项目的必需品。 文档在维护项目中起着重要作用。 Java通过使用内置的javadoc工具使文档更容易。 通过按需生成文档,Ant使其变得更加容易。
如您所知,javadoc工具非常灵活,允许许多配置选项。 Ant通过javadoc任务公开这些配置选项。 如果您不熟悉javadoc,我们建议您从本Java Documentation Tutorial开始 。
以下部分列出了Ant中使用的最常用的javadoc选项。
属性 (Attributes)
可以使用sourcepath , sourcepathref或sourcefiles指定Source。
sourcepath用于指向源文件的文件夹(例如src文件夹)。
sourcepathref用于引用path属性引用的路径(例如,delegates.src.dir)。
如果要将各个文件指定为逗号分隔列表,则使用sourcefiles 。
使用destdir文件夹(例如build.dir)指定目标路径。
您可以通过指定要包含的包名来过滤javadoc任务。 这是通过使用packagenames属性实现的,该属性是以逗号分隔的包文件列表。
您可以过滤javadoc进程以仅显示公共,私有,包或受保护的类和成员。 这是通过使用private , public , package和protected属性实现的。
您还可以使用相应的属性告诉javadoc任务包含作者和版本信息。
您还可以使用group属性将包分组在一起,以便轻松导航。
把它们放在一起
让我们继续我们的Hello world传真应用程序的主题。 让我们为我们的传真应用程序项目添加文档目标。
下面给出了我们项目中使用的示例javadoc任务。 在此示例中,我们指定了javadoc以使用src.dir作为源目录,并将doc作为目标。
我们还定制了java文档页面上显示的窗口标题,页眉和页脚信息。
此外,我们创建了三个组:
- 一个用于源文件夹中的实用程序类,
- 一个用于用户界面类,和
- 一个用于数据库相关的类。
您可能会注意到数据包组有两个包 - faxapp.entity和faxapp.dao。
<target name="generate-javadoc">
<javadoc packagenames="faxapp.*" sourcepath="${src.dir}"
destdir="doc" version="true" windowtitle="Fax Application">
<doctitle><![CDATA[= Fax Application =]]></doctitle>
<bottom>
<![CDATA[Copyright © 2011. All Rights Reserved.]]>
</bottom>
<group title="util packages" packages="faxapp.util.*"/>
<group title="web packages" packages="faxapp.web.*"/>
<group title="data packages"
packages="faxapp.entity.*:faxapp.dao.*"/>
</javadoc>
<echo message="java doc has been generated!" />
</target>
让我们执行javadoc Ant任务。 它生成并将java文档文件放在doc文件夹中。
执行javadoc target ,会产生以下结果:
C:\>ant generate-javadoc
Buildfile: C:\build.xml
java doc has been generated!
BUILD SUCCESSFUL
Total time: 10.63 second
java文档文件现在存在于doc文件夹中。
通常,javadoc文件是作为发布或包目标的一部分生成的。
Ant - Creating JAR files
编译java源文件后的下一个逻辑步骤是构建java归档文件,即JAR文件。 使用jar任务,使用Ant创建JAR文件非常简单。 jar任务的常用属性如下:
属性 | 描述 |
---|---|
basedir | 输出JAR文件的基目录。 默认情况下,它设置为项目的基本目录。 |
compress | 建议Ant在创建JAR文件时压缩文件。 |
keepcompression | 虽然compress属性适用于单个文件,但keepcompression属性执行相同的操作,但它适用于整个存档。 |
destfile | 输出JAR文件的名称。 |
duplicate | 建议Ant在找到重复文件时该怎么做。 您可以添加,保留或失败重复文件。 |
excludes | 建议Ant不要在包中包含这些以逗号分隔的文件列表。 |
excludesfile | 与上面相同,除了使用模式指定排除文件。 |
inlcudes | Inverse of excludes. |
includesfile | 反向排除文件。 |
update | 建议Ant覆盖已构建的JAR文件中的文件。 |
继续我们的Hello World传真应用程序项目,让我们添加一个新目标来生成jar文件。 但在此之前,让我们考虑下面给出的jar任务。
<jar destfile="${web.dir}/lib/util.jar"
basedir="${build.dir}/classes"
includes="faxapp/util/**"
excludes="**/Test.class"
/>
这里, web.dir属性指向Web源文件的路径。 在我们的例子中,这是util.jar的放置位置。
此示例中的build.dir属性指向build文件夹,其中可以找到util.jar的类文件。
在这个例子中,我们使用faxapp.util.*包中的类创建一个名为util.jar的jar文件。 但是,我们排除以名称Test结尾的类。 输出jar文件将放在Web应用程序lib文件夹中。
如果我们想让util.jar成为可执行的jar文件,我们需要添加带有Main-Class元属性的manifest 。
因此,上面的示例将更新为:
<jar destfile="${web.dir}/lib/util.jar"
basedir="${build.dir}/classes"
includes="faxapp/util/**"
excludes="**/Test.class">
<manifest>
<attribute name="Main-Class" value="com.iowiki.util.FaxUtil"/>
</manifest>
</jar>
要执行jar任务,请将其包装在目标(最常见的是构建或包目标)中,然后执行它们。
<target name="build-jar">
<jar destfile="${web.dir}/lib/util.jar"
basedir="${build.dir}/classes"
includes="faxapp/util/**"
excludes="**/Test.class">
<manifest>
<attribute name="Main-Class" value="com.iowiki.util.FaxUtil"/>
</manifest>
</jar>
</target>
在此文件上运行Ant会为我们创建util.jar文件。
以下结果是运行Ant文件的结果:
C:\>ant build-jar
Buildfile: C:\build.xml
BUILD SUCCESSFUL
Total time: 1.3 seconds
util.jar文件现在放在输出文件夹中。
Ant - Creating WAR files
使用Ant创建WAR文件非常简单,与创建JAR文件任务非常相似。 毕竟,WAR文件,就像JAR文件只是另一个ZIP文件。
WAR任务是JAR任务的扩展,但它有一些很好的补充,可以操作进入WEB-INF/classes文件夹的内容,并生成web.xml文件。 WAR任务对于指定WAR文件的特定布局很有用。
由于WAR任务是JAR任务的扩展,因此JAR任务的所有属性都适用于WAR任务。
属性 | 描述 |
---|---|
webxml | web.xml文件的路径 |
lib | 用于指定进入WEB-INF\lib文件夹的内容的分组。 |
classes | 用于指定进入WEB-INF\classes文件夹的内容的分组。 |
metainf | 指定生成MANIFEST.MF文件的说明。 |
继续我们的Hello World传真应用程序项目,让我们添加一个新目标来生成jar文件。 但在此之前让我们考虑战争任务。 请考虑以下示例:
<war destfile="fax.war" webxml="${web.dir}/web.xml">
<fileset dir="${web.dir}/WebContent">
<include name="**/*.*"/>
</fileset>
<lib dir="thirdpartyjars">
<exclude name="portlet.jar"/>
</lib>
<classes dir="${build.dir}/web"/>
</war>
根据前面的示例, web.dir变量引用源Web文件夹,即包含JSP,css,javascript文件等的文件夹。
build.dir变量引用输出文件夹 - 这是可以找到WAR包的类的位置。 通常,这些类将捆绑到WAR文件的WEB-INF/classes文件夹中。
在这个例子中,我们正在创建一个名为fax.war的war文件。 WEB.XML文件是从Web源文件夹获取的。 来自Web下“WebContent”文件夹的所有文件都将复制到WAR文件中。
WEB-INF/lib文件夹中填充了thirdpartyjars文件夹中的jar文件。 但是,我们排除了portlet.jar,因为它已经存在于应用程序服务器的lib文件夹中。 最后,我们将从构建目录的web文件夹中复制所有类,并将其放入WEB-INF/classes文件夹中。
将war任务包装在Ant目标(通常是包)中并运行它。 这将在指定位置创建WAR文件。
完全可以嵌套类,lib,metainf和webinf控制器,以便它们位于项目结构中任何位置的分散文件夹中。 但最佳实践表明,您的Web项目应具有与WAR文件结构类似的Web Content结构。 传真应用程序项目的结构使用此基本原则概述。
要执行war任务,请将其包装在目标(最常见的是构建或程序包目标)中,然后运行它们。
<target name="build-war">
<war destfile="fax.war" webxml="${web.dir}/web.xml">
<fileset dir="${web.dir}/WebContent">
<include name="**/*.*"/>
</fileset>
<lib dir="thirdpartyjars">
<exclude name="portlet.jar"/>
</lib>
<classes dir="${build.dir}/web"/>
</war>
</target>
在此文件上运行Ant将为我们创建fax.war文件。
以下结果是运行Ant文件的结果:
C:\>ant build-war
Buildfile: C:\build.xml
BUILD SUCCESSFUL
Total time: 12.3 seconds
fax.war文件现在放在输出文件夹中。 war文件的内容将是:
fax.war:
+---jsp <i>This folder contains the jsp files</i>
+---css <i>This folder contains the stylesheet files</i>
+---js <i>This folder contains the javascript files</i>
+---images <i>This folder contains the image files</i>
+---META-INF <i>This folder contains the Manifest.Mf</i>
+---WEB-INF
+---classes <i>This folder contains the compiled classes</i>
+---lib <i>Third party libraries and the utility jar files</i>
WEB.xml <i>Configuration file that defines the WAR package</i>
Ant - Packaging Applications
我们已经使用Hello World传真Web应用程序逐点了解Ant的不同方面。
现在是时候把所有东西放在一起来创建一个完整而完整的build.xml文件。 考虑build.properties和build.xml文件,如下所示:
build.properties
deploy.path=c:\tomcat6\webapps
build.xml
<?xml version="1.0"?>
<project name="fax" basedir="." default="usage">
<property file="build.properties"/>
<property name="src.dir" value="src"/>
<property name="web.dir" value="war"/>
<property name="javadoc.dir" value="doc"/>
<property name="build.dir" value="${web.dir}/WEB-INF/classes"/>
<property name="name" value="fax"/>
<path id="master-classpath">
<fileset dir="${web.dir}/WEB-INF/lib">
<include name="*.jar"/>
</fileset>
<pathelement path="${build.dir}"/>
</path>
<target name="javadoc">
<javadoc packagenames="faxapp.*" sourcepath="${src.dir}"
destdir="doc" version="true" windowtitle="Fax Application">
<doctitle><![CDATA[<h1>= Fax Application =</h1>]]>
</doctitle>
<bottom><![CDATA[Copyright © 2011. All Rights Reserved.]]>
</bottom>
<group title="util packages" packages="faxapp.util.*"/>
<group title="web packages" packages="faxapp.web.*"/>
<group title="data packages"
packages="faxapp.entity.*:faxapp.dao.*"/>
</javadoc>
</target>
<target name="usage">
<echo message=""/>
<echo message="${name} build file"/>
<echo message="-----------------------------------"/>
<echo message=""/>
<echo message="Available targets are:"/>
<echo message=""/>
<echo message="deploy --> Deploy application as directory"/>
<echo message="deploywar --> Deploy application as a WAR file"/>
<echo message=""/>
</target>
<target name="build" description="Compile main
source tree java files">
<mkdir dir="${build.dir}"/>
<javac destdir="${build.dir}" source="1.5"
target="1.5" debug="true"
deprecation="false" optimize="false" failonerror="true">
<src path="${src.dir}"/>
<classpath refid="master-classpath"/>
</javac>
</target>
<target name="deploy" depends="build"
description="Deploy application">
<copy todir="${deploy.path}/${name}"
preservelastmodified="true">
<fileset dir="${web.dir}">
<include name="**/*.*"/>
</fileset>
</copy>
</target>
<target name="deploywar" depends="build"
description="Deploy application as a WAR file">
<war destfile="${name}.war"
webxml="${web.dir}/WEB-INF/web.xml">
<fileset dir="${web.dir}">
<include name="**/*.*"/>
</fileset>
</war>
<copy todir="${deploy.path}" preservelastmodified="true">
<fileset dir=".">
<include name="*.war"/>
</fileset>
</copy>
</target>
<target name="clean" description="Clean output directories">
<delete>
<fileset dir="${build.dir}">
<include name="**/*.class"/>
</fileset>
</delete>
</target>
</project>
在这个例子中:
我们首先在构建属性文件中将Tomcat中webapps文件夹的路径声明为deploy.path变量。
我们还在src.dir变量中声明了java文件的源文件夹。
然后我们在web.dir变量中声明web文件的源文件夹。 javadoc.dir是用于存储java文档的文件夹, build.dir是用于存储构建输出文件的路径。
然后我们声明Web应用程序的名称,在我们的例子中是fax 。
我们还定义了主类路径,其中包含项目的WEB-INF/lib文件夹中存在的JAR文件。
我们还在master类路径中包含build.dir中存在的类文件。
Javadoc目标生成项目所需的javadoc,使用目标用于打印构建文件中存在的公共目标。
上面的示例显示了两个部署目标: deploy和deploywar.
部署目标将文件从Web目录复制到deploy目录,同时保留上次修改的日期时间戳。 在部署到支持热部署的服务器时,这非常有用。
clean目标清除所有以前构建的文件。
deploywar目标构建war文件,然后将war文件复制到应用程序服务器的deploy目录。
Ant - Deploying Applications
在上一章中,我们学习了如何打包应用程序并将其部署到文件夹。
在本章中,我们将把Web应用程序直接部署到应用程序服务器部署文件夹,然后我们将添加一些Ant目标来启动和停止服务。 让我们继续使用Hello World传真Web应用程序。 这是前一章的延续,新组件以粗体突出显示。
build.properties
# Ant properties for building the springapp
appserver.home=c:\\install\\apache-tomcat-7.0.19
# for Tomcat 5 use $appserver.home}/server/lib
# for Tomcat 6 use $appserver.home}/lib
appserver.lib=${appserver.home}/lib
deploy.path=${appserver.home}/webapps
tomcat.manager.url=http://www.iowiki.com:8080/manager
tomcat.manager.username=iowiki
tomcat.manager.password=secret
build.xml
<?xml version="1.0"?>
<project name="fax" basedir="." default="usage">
<property file="build.properties"/>
<property name="src.dir" value="src"/>
<property name="web.dir" value="war"/>
<property name="javadoc.dir" value="doc"/>
<property name="build.dir" value="${web.dir}/WEB-INF/classes"/>
<property name="name" value="fax"/>
<path id="master-classpath">
<fileset dir="${web.dir}/WEB-INF/lib">
<include name="*.jar"/>
</fileset>
<pathelement path="${build.dir}"/>
</path>
<target name="javadoc">
<javadoc packagenames="faxapp.*" sourcepath="${src.dir}"
destdir="doc" version="true" windowtitle="Fax Application">
<doctitle><![CDATA[<h1>= Fax Application
=</h1>]]></doctitle>
<bottom><![CDATA[Copyright © 2011. All
Rights Reserved.]]></bottom>
<group title="util packages" packages="faxapp.util.*"/>
<group title="web packages" packages="faxapp.web.*"/>
<group title="data packages" packages="faxapp.entity.*:faxapp.dao.*"/>
</javadoc>
</target>
<target name="usage">
<echo message=""/>
<echo message="${name} build file"/>
<echo message="-----------------------------------"/>
<echo message=""/>
<echo message="Available targets are:"/>
<echo message=""/>
<echo message="deploy --> Deploy application as directory"/>
<echo message="deploywar --> Deploy application as a WAR file"/>
<echo message=""/>
</target>
<target name="build" description="Compile main
source tree java files">
<mkdir dir="${build.dir}"/>
<javac destdir="${build.dir}" source="1.5" target="1.5" debug="true"
deprecation="false" optimize="false" failonerror="true">
<src path="${src.dir}"/>
<classpath refid="master-classpath"/>
</javac>
</target>
<target name="deploy" depends="build" description="Deploy application">
<copy todir="${deploy.path}/${name}"
preservelastmodified="true">
<fileset dir="${web.dir}">
<include name="**/*.*"/>
</fileset>
</copy>
</target>
<target name="deploywar" depends="build"
description="Deploy application as a WAR file">
<war destfile="${name}.war"
webxml="${web.dir}/WEB-INF/web.xml">
<fileset dir="${web.dir}">
<include name="**/*.*"/>
</fileset>
</war>
<copy todir="${deploy.path}" preservelastmodified="true">
<fileset dir=".">
<include name="*.war"/>
</fileset>
</copy>
</target>
<target name="clean" description="Clean output directories">
<delete>
<fileset dir="${build.dir}">
<include name="**/*.class"/>
</fileset>
</delete>
</target>
<!-- ============================================================ -->
<!-- Tomcat tasks -->
<!-- ============================================================ -->
<path id="catalina-ant-classpath">
<!-- We need the Catalina jars for Tomcat -->
<!-- * for other app servers - check the docs -->
<fileset dir="${appserver.lib}">
<include name="catalina-ant.jar"/>
</fileset>
</path>
<taskdef name="install" classname="org.apache.catalina.ant.InstallTask">
<classpath refid="catalina-ant-classpath"/>
</taskdef>
<taskdef name="reload" classname="org.apache.catalina.ant.ReloadTask">
<classpath refid="catalina-ant-classpath"/>
</taskdef>
<taskdef name="list" classname="org.apache.catalina.ant.ListTask">
<classpath refid="catalina-ant-classpath"/>
</taskdef>
<taskdef name="start" classname="org.apache.catalina.ant.StartTask">
<classpath refid="catalina-ant-classpath"/>
</taskdef>
<taskdef name="stop" classname="org.apache.catalina.ant.StopTask">
<classpath refid="catalina-ant-classpath"/>
</taskdef>
<target name="reload" description="Reload application in Tomcat">
<reload url="${tomcat.manager.url}"username="${tomcat.manager.username}"
password="${tomcat.manager.password}" path="/${name}"/>
</target>
</project>
在这个例子中,我们使用Tomcat作为我们的应用服务器。 首先,在构建属性文件中,我们定义了一些其他属性。
appserver.home指向Tomcat应用程序服务器的安装路径。
appserver.lib指向Tomcat安装文件夹中的库文件。
deploy.path变量现在指向Tomcat中的webapp文件夹。
可以使用Tomcat管理器应用程序停止和启动Tomcat中的应用程序。 管理器应用程序的URL,用户名和密码也在build.properties文件中指定。 接下来,我们声明一个包含catalina-ant.jar的新CLASSPATH。 需要此jar文件才能通过Apache Ant执行Tomcat任务。
catalina-ant.jar提供以下任务:
属性 | 描述 |
---|---|
InstallTask | 安装Web应用程序。 类名:org.apache.catalina.ant.InstallTask |
ReloadTask | 重新加载Web应用程序。 类名:org.apache.catalina.ant.ReloadTask |
ListTask | 列出所有Web应用程序。 类名:org.apache.catalina.ant.ListTask |
StartTask | 启动Web应用程序。 类名:org.apache.catalina.ant.StartTask |
StopTask | 停止Web应用程序。 类名:org.apache.catalina.ant.StopTask |
ReloadTask | 无需停止即可重新加载Web应用程序。 类名:org.apache.catalina.ant.ReloadTask |
重新加载任务需要以下附加参数:
- 管理器应用程序的URL
- 用于重新启动Web应用程序的用户名
- 重启Web应用程序的密码
- 要重新启动的Web应用程序的名称
让我们发出deploy-war命令将webapp复制到Tomcat webapps文件夹,然后让我们重新加载Fax Web应用程序。 以下结果是运行Ant文件的结果:
C:\>ant deploy-war
Buildfile: C:\build.xml
BUILD SUCCESSFUL
Total time: 6.3 seconds
C:\>ant reload
Buildfile: C:\build.xml
BUILD SUCCESSFUL
Total time: 3.1 seconds
运行上述任务后,将部署Web应用程序并重新加载Web应用程序。
Ant - Executing Java code
您可以使用Ant来执行Java代码。 在以下示例中,java类接受参数(管理员的电子邮件地址)并发送电子邮件。
public class NotifyAdministrator
{
public static void main(String[] args)
{
String email = args[0];
notifyAdministratorviaEmail(email);
System.out.println("Administrator "+email+" has been notified");
}
public static void notifyAdministratorviaEmail(String email
{
//......
}
}
这是一个执行此java类的简单构建。
<?xml version="1.0"?>
<project name="sample" basedir="." default="notify">
<target name="notify">
<java fork="true" failonerror="yes" classname="NotifyAdministrator">
<arg line="admin@test.com"/>
</java>
</target>
</project>
执行构建时,会产生以下结果:
C:\>ant
Buildfile: C:\build.xml
notify: [java] Administrator admin@test.com has been notified
BUILD SUCCESSFUL
Total time: 1 second
在这个例子中,java代码做了一件简单的事 - 发送电子邮件。 我们本可以使用内置的Ant任务来做到这一点。 但是,现在您已经了解了这个想法,您可以扩展构建文件以调用执行复杂操作的java代码,例如:加密源代码。
Ant - Eclipse Integration
如果您已经下载并安装了Eclipse,那么您就没什么可做的了。 Eclipse预先捆绑了Ant插件,随时可以使用。
按照简单的步骤,将Ant集成到Eclipse中。
确保build.xml是java项目的一部分,并且不驻留在项目外部的位置。
按照Window 》 Show View 》 Other 》 Ant 》 Ant.启用Ant视图Window 》 Show View 》 Other 》 Ant 》 Ant.
打开Project Explorer,将build.xml拖到Ant视图中。
您的Ant视图类似于:
单击目标,build/clean/usage将使用目标运行Ant。
单击“传真”将执行默认目标 - usage.
Ant Eclipse插件还附带了一个用于编辑build.xml文件的良好编辑器。 编辑器知道build.xml模式,可以帮助您完成代码。
要使用Ant编辑器,请右键单击build.xml(从Project Explorer),然后选择Open with> Ant Editor。 Ant编辑器看起来应该类似于:
Ant编辑器在右侧列出目标。 目标列表用作书签,允许您直接跳转到编辑特定目标。
Ant - JUnit Integration
JUnit是基于Java的开发的常用单元测试框架。 它易于使用且易于扩展。 有许多JUnit扩展可用。 如果您不熟悉JUnit,请从www.junit.org下载并阅读其手册。
本章介绍如何使用Ant执行JUnit测试。 Ant通过JUnit任务直接进行。
JUnit任务的属性如下所示:
属性 | 描述 |
---|---|
dir | 从哪里调用VM。 禁用fork时会忽略此项。 |
jvm | 用于调用JVM的命令。 禁用fork时会忽略此项。 |
fork | 在单独的JVM中运行测试 |
errorproperty | 如果存在JUnit错误,则设置的属性的名称 |
failureproperty | 如果存在JUnit失败,则设置的属性的名称 |
haltonerror | 发生测试错误时停止执行 |
haltonfailure | 发生故障时停止执行 |
printsummary | 建议Ant为每个测试显示简单的统计信息 |
showoutput | 建议Ant将输出发送到其日志和格式化程序 |
tempdir | Ant将使用的临时文件的路径 |
timeout | 退出运行时间比此设置长的测试(以毫秒为单位)。 |
让我们继续Hello World传真Web应用程序的主题并添加一个JUnit目标。
以下示例显示了一个简单的JUnit测试执行:
<target name="unittest">
<junit haltonfailure="true" printsummary="true">
<test name="com.iowiki.UtilsTest"/>
</junit>
</target>
此示例显示了com.iowiki.UtilsTest junit类上JUnit的执行情况。 运行上面的代码会产生以下输出:
test:
[echo] Testing the application
[junit] Running com.iowiki.UtilsTest
[junit] Tests run: 12, Failures: 0, Errors: 0, Time elapsed: 16.2 sec
BUILD PASSED
Ant - Extending Ant
Ant带有一组预定义的任务,但您可以创建自己的任务,如下例所示。
自定义Ant任务应扩展org.apache.tools.ant.Task类,并应扩展execute()方法。 以下是一个简单的例子:
package com.iowiki.ant;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.BuildException;
public class MyTask extends Task {
String message;
public void execute() throws BuildException {
log("Message: " + message, Project.MSG_INFO);
}
public void setMessage(String message) {
this.message= message;
}
}
要执行自定义任务,您需要将以下内容添加到Hello World传真Web应用程序:
<target name="custom">
<taskdef name="custom" classname="com.iowiki.ant.MyTask" />
<custom message="Hello World!"/>
</target>
执行上述自定义任务会打印消息“Hello World!”
c:\>ant custom
test:
[custom] Message : Hello World!
elapsed: 0.2 sec
BUILD PASSED
这只是一个简单的示例,您可以使用Ant的强大功能来执行您想要的任何操作来改进构建和部署过程。