3.3.1 ANT工具简介
有没有一个好的工具来帮助人们完成上述这些麻烦的任务呢?答案是有的,它就是Ant工具。Ant是Apache软件基金会Jakarta项目中的一个子项目,是一个基于Java的构建应用程序的工具。根据它的首创者James Duncan Davidson的解释,其名称是Another Neat Tool的首字母缩写,意为另一个干净灵巧的工具。这一缩写却变成了蚂蚁,说来也是因缘巧合,Ant工具的确有几分蚂蚁的天性,比如个头小而负重能力强。还由于它本身是用Java写的,天生就有很好的跨平台的能力,正像蚂蚁有很强的环境适应能力。因此得到了广泛的应用。对于那些建立传统Java应用程序和那些使用HTML、JSP和Servlet以及本书所介绍的框架创建Web应用程序的人来说,Ant极具价值。无论您的Java开发者使用什么操作系统、集成开发环境或者构建环境,Ant都可以将您的工程有机地组合在一起。一些用来开发应用程序的集成开发环境(IDE)实际上也是用Ant来完成我们前面谈到的建目录、拷贝文件、编译及部署等等这些构建应用程序的任务的。
Ant使用build文件来创建应用程序。build文件是一个.xml文件,缺省的文件名为build.xml。它包含有一个项目(project)元素,项目下包含若干(至少要有一个)目标(target),目标下包含任务(task)元素。每个任务元素就是一段可执行的代码。每个任务可以有多个属性(attribute)。任务的一般结构 如下:
- <name attribute1="value1" attribute2="value2"…/>
Ant还可以包含一个属性(property)的集合。这些属性(property)可以用任务的形式写在build文件内,也可以写在专门的.properties文件中。一个属性(property)有一个名字和一个值,其名字是大小写敏感的。属性(property)可以被用在任务的属性(attributes)值中,使用的方法是将属性(property)名放在“${”与“}”之间,作为任务的属性(attributes)值。比如,有一个名为src.dir的属性(property),其值为src,则该属性(property)能够以${src.dir}/model形式用在任务的属性(attributes)值中,该值在运行时被解析为src/model。此外,Ant还有一些内建的属性(property)如,操作系统名,项目的基本目录basedir等。
知道这些基本的知识后,我们就可以用Ant来按照与我们手工构建应用程序类似的过程来构建上面的登录例子应用程序了。
3.3.2 创建build.xml文件
使用Ant工具构建和部署应用程序的最主要的任务就是创建build.xml文件。每个应用程序项目对应一个build.xml文件,该文件放在项目的根目录下。下面,我们结合Hello World示例应用程序来看一下创建build.xml文件的过程。
build.xml文件中根元素是<project>元素,其他的元素都包含在该元素中。示例应用中的<project>元素如下:
- <project default="deploy" basedir=".">
这一句定义一个Ant项目,项目有一个可选的名称属性,这里省略了,该项目的缺省目标是部署(deploy),项目的基准目录是当前目录,也就是项目目录本身,其他的目录都是以它为基准算出来的。build.xml文件也在该目录中。
该句后面紧接着的是一系列的属性设置,如项目名、Web应用程序名及各种目录。
3.3.2.1 设置属性
每个应用程序项目都有一些属性,如在项目的目录方面就有:项目的根目录、项目中存放应用程序源代码的目录、Web应用的根目录、应用程序要发布到的服务器所在的目录;一个完整的应用程序项目的目录结构中还包含诸如JavaDoc这样的文档目录和Ant工具用来创建项目时使用的一些临时性的目录,如build目录和存放打包文件的目录等。
示例应用中的属性定义如下:
- <property name="project.name" value="hello" />
- <property name="webapp.name" value="hello"/>
- <property name="build.dir" value="${basedir}/build" />
- <property name="src.dir" value="${basedir}/src" />
- <property name="src.java.dir" value="${src.dir}/com" />
- <property name="web.dir" value="${basedir}/WebRoot" />
- <property name="lib.dir" value="${web.dir}/WEB-INF/lib" />
- <property name="dist.dir" value="${basedir}/dist" />
- <property name="warfile" value="${dist.dir}/${webapp.name}.war"/>
- <property environment="env"/>
- <property name="tomcat.dir" value="${env.CATALINA_HOME}"/>
从这些属性的名字可以看出,它们绝大多数都是非常直白的,一看就知道指的是什么,就不用多说。这里有必要指出的是:
- <property environment="env"/>
这一句与众不同,它不是以名称=xx、值=xx的形式出现,而是以environment=前缀的形式出现,它的用途是用来引用我们在操作系统中设置的环境变量的,规定就是以这种格式来运用的。根据Ant的参考文档,定义属性的方法有六种,有需要的读者可以去查阅该文档。我们的示例build.xml只涉及到了其中的两种形式。
3.3.2.2 设置classpath
在设置完属性后,接下来要做的是设置编译Java源程序时所要用到的classpath,也就是我们在手工编译应用程序时,出现在javac命令中的-classpath后面的内容,这些内容往往是项目的lib目录中的一些.jar或者.zip文件,或者是应用程序服务器的lib目录中的一些.jar或者.zip文件,在我们的示例应用中所用到的是在作为应用程序服务器的Tomcat的lib目录下的.jar文件。因此,该build.xml文件的设置classpath的代码如下:
- <path id="classpath">
- <fileset dir="${tomcat.dir}/lib">
- <include name="**/*.jar"/>
- </fileset>
- <fileset dir="${lib.dir}">
- <include name="**/*.jar"/>
- </fileset>
- </path>
在完成属性和classpath的设置后,接下来我们要定义一系列的目标。首先,就是用来做清理工作的目标——clean目标,它要完成的任务是将构建应用程序时临时要用到的build目录删除掉,以免以前残存的内容影响新创建的内容。其代码如下:
- <target name="clean" >
- <delete dir="${build.dir}" />
- </target>
接下来是一个做准备工作的目标,prepare目标。它的任务是建立一个用来构建应用程序的新的build目录结构。它的代码如下:
- <target name="prepare" depends="clean"
- description="Create build directories.">
- <mkdir dir="${build.dir}/${project.name}" />
- <mkdir dir="${build.dir}/${project.name}/WEB-INF" />
- <mkdir dir="${build.dir}/${project.name}/WEB-INF/classes" />
- <mkdir dir="${build.dir}/${project.name}/WEB-INF/lib" />
- </target>
有了build目录后,我们就要将lib目录下的库文件拷贝到build目录中对应的lib目录中,这就是deploy.copyJars这个目标的任务。代码如下:
- <target name="deploy.copyJars">
- <copy todir="${build.dir}/${project.name}/WEB-INF/lib">
- <fileset dir="${lib.dir}">
- <include name="**/*.jar"/>
- <include name="**/*.dtd"/>
- </fileset>
- </copy>
- </target>
有了前面这些准备工作后,现在有条件来构建应用程序了,这就是build目标的职责。build目标主要完成两大任务:其一,是编译Java类的源文件;其二,是将一些静态文件拷贝到build目录下的相应目录中去。其代码如下:
- <target name="build" depends="prepare,deploy.copyJars"
- description="Compile Java files and copy static files." >
- <javac srcdir="${src.java.dir}" destdir=
- "${build.dir}/${project.name}/WEB-INF/classes">
- <include name="**/*.java" />
- <classpath refid="classpath"/>
- </javac>
- <copy todir="${build.dir}/${project.name}/WEB-INF">
- <fileset dir="${web.dir}/WEB-INF">
- <include name="*.xml" />
- <include name="*.tld" />
- </fileset>
- </copy>
- <copy todir="${build.dir}/${project.name}/">
- <fileset dir="${web.dir}">
- <include name="*.html" />
- <include name="*.gif" />
- <include name="*.jpg" />
- <include name="*.jsp" />
- <include name="*.xml" />
- <include name="*.css" />
- </fileset>
- </copy>
- <copy todir="${build.dir}/${project.name}/WEB-INF/classes">
- <fileset dir="${src.java.dir}">
- <include name="**/*.properties" />
- <include name="**/*.xml" />
- <exclude name="**/*.java" />
- </fileset>
- </copy>
- </target>
Web应用程序一般会被打包成Web归档文件即.war形式的文件后再发布(供别人学习的或正在开发中的应用程序也往往直接发布没有打包的目录结构)。build.war目标就是用来打包Web应用程序的,它的代码如下:
- <target name="build.war" depends="build">
- <delete dir="${dist.dir}" />
- <mkdir dir="${dist.dir}" />
- <!-- create a war file for distribution -->
- <jar destfile="${dist.dir}/${webapp.name}.war"
- basedir="${build.dir}/${project.name}"/>
- <delete dir="${build.dir}" />
- </target>
deploy目标是本示例应用程序项目的最后一个目标,顾名思义,它的任务就是用来部署应用程序的,部署应用程序最简单也是最常用的方法就是将应用程序的.war文件或者是目录结构拷贝到应用服务器缺省的应用程序发布目录下,在使用Tomcat做应用程序服务器的情况下就是拷贝到Tomcat的webapp目录下。代码如下:
- <target name="deploy" depends="build.war">
- <copy file="${warfile}" todir="${tomcat.dir}/webapps"/>
- <delete dir="${dist.dir}"/>
- </target>
有了build.xml文件后,用它来构建和部署应用程序就很简单了。具体方法如下:
打开一个DOS窗口,将当前目录切换到要构建的应用程序项目的根目录下,如在Hello World示例应用程序中就是切换到hello目录,在DOS提示符下输入ant后回车就可以了。
工作程序如下:从build.xml文件中的代码可以看出,该Ant项目的缺省目标是deploy,但该目标依赖于build.war目标,而build.war目标又依赖于build目标,由此类推,这将导致build.xml文件中的所有目标都被执行,最后完成应用程序的构建和部署。
这里要说明一下的是,这个build.xml文件只是一个示例,您完全可以根据您项目的实际情况设置不同的属性、目标等。
如果您的应用程序的目录结构与Hello World示例应用程序的目录结构类似,也可以使用该build.xml文件来构建和部署您的应用程序,只是要根据您的实际情况更改如下两句:
- <property name="project.name" value="aaaa" />
- <property name="webapp.name" value="hello"/>