Ant的使用

来源:互联网 发布:体育科研数据分析 编辑:程序博客网 时间:2024/05/18 06:09

来源:http://book.51cto.com/art/200806/78059.htm

 

 

第9章  Ant工具的使用

Ant是著名Java开源组织Apache的一个项目,是一个基于Java的批处理工具。Ant是Another Neat Tool(另一个整洁的工具)的首字母缩写。它可以使你通过Ant脚本语言,自动将项目拷贝到某个目录,发布项目,或者生成一些代码,执行SQL语言等。总之,它可以帮助你完成项目开发中除了开发代码以外的大部分辅助性工作。

C或C++中的传统项目经常使用make工具来做这件事情,其中生成任务是通过调用shell命令来执行的,而依赖关系定义在每个生成文件之间,以便它们总是以必需的顺序执行。Ant与make类似,它也定义生成文件之间的依赖关系;然而,与使用特定于平台的shell命令来实现生成过程所不同的是,它使用跨平台的Java类。使用Ant,您能够编写单个生成文件,这个生成文件在任何Java平台上都一致地操作(因为Ant本身也是使用Java语言来实现的),这就是Ant最大的优势。

Ant的其他关键优势包括其突出的简单性和无缝地使用自定义功能来扩展它的能力。Ant主要是设计用于生成Java项目的,但这并不是它唯一的用途。我们发现它对其他任务也很有帮助,比如以跨平台的方式执行文件系统操作。此外,还有许多可用的第三方Ant任务,而编写自定义的Ant任务也是相对简单的,因此很容易针对特定的应用程序定制Ant。

9.1  Ant的安装使用

1.安装

Ant安装很简单,只要从Apache网站上下载它的zip包,然后解压到任何本地磁盘上,在环境变量中更新Path的值,加上“%ANT_HOME%/bin”就可以了,这样在DOS提示符中就可以使用Ant这个命令了。你还需要设置一下“ANT_HOME”这个环境变量,也就是解压后存放的目录。还有就是要检查一下JDK安装目录,确定“JAVA_HOME”是不是已加到环境变量中了。

2.使用概述

(1)基本概念

使用Ant也同样是非常简单的事。通常的做法就是在项目中建立一个XML文件,名字通常可以取“build.xml”,当然可以取任何喜欢的名字。这个文件就是需要Ant为项目做的一些辅助性工作的批处理文件。它的格式可能类似于以下实例。我们先不具体说Ant标记,先有一个感性的认识会比较快上手。

例子:

<?xml version="1.0" encoding="UTF-8"?>
<project default="all" name="pluto-project" basedir=".">
    <target name="all" depends="api, container, portal">
    </target>
    <target name="clean" depends="api-clean, container-clean, portal- clean">
    </target>
    <target name="api">
       <property name="final.name" value="portlet-api-@@DATE@@"/>
       <ant antfile="build.xml" dir="api" target="jar" inheritAll="false" />
    </target>
    <target name="api-clean">
       <ant antfile="build.xml" dir="api" target="clean" inheritAll="false" />
    </target>
    <target name="container" depends="api">
       <ant antfile="build.xml" dir="container" target="jar" inheritAll= "false" />
    </target>
    <target name="container-clean">
       <ant antfile="build.xml" dir="container" target="clean" inheritAll= "false" />
    </target>
    <target name="portal" depends="container">
       <ant antfile="build.xml" dir="portal" target="jar" inheritAll= "false"/>
    </target>
    <target name="portal-clean">
       <ant antfile="build.xml" dir="portal" target="clean" inheritAll= "false" />
    </target>
</project>

① project及target标签

这个build.xml文件引自Apache的一个项目。里面可以看到有project以及target标签。有些项目的build.xml可能不是以<?xml version="1.0" encoding="UTF-8"?>开头的,这也没关系。

每一个build.xml只能有一个project标签,每个project标签里面包含了几个tartget标签。每一个target可以独立执行或者依赖于其他target执行完毕才能执行。

project有下面的属性:
 
name,项目名称;
 
default,当没有指定target时使用的缺省target;
 
basedir,用于计算所有其他路径的基路径。该属性可以被basedir property覆盖。当覆盖时,该属性被忽略。如果属性和basedir property都没有设定,就使用buildfile文件的父目录。

target有下面的属性:
 
name,target的名字;
 
depends,用逗号分隔的target的名字列表,也就是依赖表;
 
if,执行target所需要设定的属性名;
 
unless,执行target需要清除设定的属性名;
 
description,关于target功能的简短描述。

以下是一个典型的例子。

 <target name="A"/>
<target name="B" depends="A"/>
<target name="C" depends="B"/>
<target name="D" depends="C,B,A"/>

其中target A可以独立执行,但是B、C、D则依赖于其他target才可以执行。也就是说,执行D,Ant就会按照A- B- C这样的顺序先执行其他target。

project标签里面有一个default="all",这就是说明了在默认情况下,all这个target会被执行。

② 定义变量

在这个文件中没有看到属性定义,其实如果想使用定义变量,可以在project标签下定义如下面这样的标签:

 <project ……>
<property name="src" location="src"/>
  <property name="build" location="build"/>
<target ……>

这样在引用的时候就可以使用形如“${build}”这样的变量了,省得自己去修改每一处需要用到变量的地方。

<target name="init">
……
<mkdir dir="${build}"/>
……
</target>

另外,我们可以使用一个外置的属性文件:build.properties,以name=value方式定义变量。

然后在build.xml中添加<property file="build.properties" />以便引用这个文件。使用外部的属性文件可以保存一些预设置的公共属性变量。这些属性可以在多个不同的Build文件中使用。我们在项目中使用的就是这种方式。

③ 添加目录操作

<target name="init">
              <mkdir dir="${dist.dir}" />
              <mkdir dir="${dist.classes.dir}" />
              <mkdir dir="${dist.webapps.dir}" />
</target>  

这里的dist.dir等用${}括起来的,是我们定义的变量。

④ 编译Java文件的操作

<target name="compile">
               <javac srcdir="${src.dir}" destdir="$
{dist.classes.dir}" debug ="true" encoding="GBK">
               <classpath refid="classpath" />
               </javac>

<jar destfile="${dist.classes.dir}/lib/app.jar"
basedir= "${dist. classes.dir}"/>

</target>

这里说一下javac这个任务标签。

其中看到有srcdir、destdir、debug、encoding等属性,还有一个classpath的子标签。srcdir就是目标source,需要编译的源文件;destdir就是目的地,编译出来的class的存放地;debug参数是指明source是不是需要把debug信息编译进去,如果不加这个参数,等于在命令行后面加上-g:none这个参数;encoding这个参数指明以何种编码方式编码source文件,对于有中文文字的代码来说这项比较重要。

classpath指明了你需要应用的jar包,或者其他class文件的所在地,这也是非常重要的一个选项。使用方式有以下几种。

 <property name="lib.dir" value="${basedir}/lib" />
…….
<path id="classpath">
             <fileset dir="${lib.dir}">
                 <include name="*.jar"/>
             </fileset>
</path>
……
<classpath refid="classpath" />

作为classpath引用预先定义的jar包位置,refid指明了一个引用变量。一般在real-world情况下会这样使用。

简单的使用是这样的:

 <javac srcdir="${src}"
       destdir="${build}"
       classpath="xyz.jar"
   debug="on"
/>

⑤ 打jar包操作

<jar destfile="${dist}/lib/app.jar" basedir="${dist.classes.dir}"/>

这个就是把编译好的文件打成jar包的Ant脚本,和上面javac一样,可以放在任意位置。很明显,destfile就是想要打成的包,basedir就是目标class文件,其他的复杂参数手册上都有,可以对照参考。

<jar destfile="${dist}/lib/app.jar">
    <fileset dir="${build}/classes"
        excludes="**/Test.class"
/>
    <fileset dir="${src}/resources"/>
</jar>

上面这段脚本也很容易理解,就是除了Test.class文件以外,把一个source的resource目录,连同编译后的class脚本一起打进app.jar包内。

⑥ 复制文件操作

<copy todir="${dist.webapps.dir}/WEB-INF/lib" overwrite="true" flatten= "true">
        <fileset dir="${lib.dir}">
          <include name="*.jar" />
          <exclude name="j2ee.jar" />
        </fileset>
</copy>

上面脚本很容易理解。todir指定了需要拷贝的地点,overwrite是否需要覆盖,flatten是否忽略目的目录结构,不管是什么目录,直接拷贝文件到目的地,丢弃其所在结构。

 <fileset dir="${lib.dir}">
         <include name="*.jar" />
         <exclude name="j2ee.jar" />
</fileset>

选定除了j2ee.jar包以外的所有在lib.dir变量中所定义的包下面的jar包。

⑦ 其他拷贝样式

文件到目录拷贝:

<copy file="myfile.txt" todir="../some/other/dir"/>

目录到目录拷贝:

<copy todir="../new/dir">
    <fileset dir="src_dir"/>
</copy>

比较有用的命令:

<copy todir="../backup/dir">
  <fileset dir="src_dir"/>
  <filterset>
   <filter token="TITLE" value="Foo Bar"/>
  </filterset>
</copy>

拷贝sr_dir目录到backup/dir目录,并且把所有文件中的@TITLE@替换成Foo Bar。还有很多用法,等到使用的时候可以去查手册。


⑧ 删除操作

<target name="clean">
       <delete dir="${dest.dir}"/>
       <delete file="${dest2.dir}"/>
    </target> 

以上操作也是很容易理解的。

(2)高级话题

① 在J2EE项目中的应用

只要掌握了Ant的使用方法,在J2EE项目中的应用与在其他项目中的应用并没有太大的不同,但是仍有几点是需要注意的。
 
要清楚War和Jar文件的目录结构,主要是War的配置文件web.xml的位置和EJB的配置文件(ejb-jar.xml和weblogic-ejb-jar.xml等)的位置,在调用Jar任务打包文件时一定要记得把它们也包含进来。一般在编译之前就要注意把这些需打包的文件拷入相应目录下。
 
在J2EE项目中可能会涉及一些特殊的任务,比如在WebLogic中会调用ejbc预编译EJB的代码存根,或者需要在Ant中同时发布Jar到相应的服务器中等。可以用两种途径实现这些任务,一是扩展Ant任务实现这些任务,二是直接用Java任务来执行这些命令。下面代码是打包、发布一个EJB的build.xml配置文件片段。

<target name="deploy_HelloEJB" depends="compile">
<delete dir="${temp}/ejb_make"/> <!-- 首先删除临时目录 -->
<delete file="${temp}/helloEJB.jar"/>
<!-- 删除WebLogic域中老版本的EJB -->
<delete file="${weblogic.deploy.dest}/helloEJB.jar"/>
<!-- 创建META-INF目录,放置ejb-jar.xml和weblogic-ejb-jar.xml -->
<mkdir dir="${temp}/ejb_make/META-INF"/>
<!-- 拷贝ejb-jar.xml和weblogic-ejb-jar.xml 到临时目录-->
<copy todir="${temp}/ejb_make/META-INF">
<fileset dir="etc/baseinfo">
<include name="*.xml"/>
</fileset>
</copy>
<!-- 拷贝所有的helloEJB类到临时目录 -->
<copy todir="${temp}/ejb_make/">
<fileset dir="${dest.classes}/"> <!-- dest.classes是输出的类文件目录 -->
<include name="${dest.classes}/helloEJB/**"/>
</fileset>
</copy>
<!-- 将所有这些文件打包成helloEJB.jar -->
<jar jarfile="${temp}/helloEJB.jar" basedir="${temp}/ejb_make"/>
<!-- 进行weblogic.ejbc编译 -->
<java classpath="${wl_cp}" classname="weblogic.ejbc" fork="yes" >
<classpath>
<fileset dir="lib">
<include name="*.jar" />
</fileset>
</classpath>
<arg value="${temp}/helloEJB.jar" />
<arg value="${temp}/helloEJB_deploy.jar" />
</java>
<!-- 拷贝/发布到WebLogic的{DOMAIN}/applications目录 -->
<copy file="${temp}/helloEJB_deploy.jar" todir="${weblogic.deploy. dest}"/>
</target>

② 用Ant配合JUnit实现单元测试

Ant提供了JUnit任务,可以执行单元测试代码。如何使用JUnit,以及如何编写测试用例(TestCase),感兴趣的读者可以参阅JUnit的相关文档。在Ant中使用JUnit的方法非常简单,首先需要把junit.jar拷入ANT_HOME/lib下,确认在这个目录下有optional.jar,因为JUnit是Ant的扩展任务,需要引用这个扩展包。然后就是在Build文件中加入JUnit的任务,如下:

<target name="run" depends="client">
<junit printsummary="yes" fork="yes" haltonfailure="yes">
<classpath>
<pathelement location="client.jar" />
</classpath>
<formatter type="plain" />
<test name="com.ascenttech.HelloWorldTest" />
</junit>
</target>

3.执行Ant脚本

在有build.xml的目录提示符下使用Ant就可以了。如果是其他的名字,那么就使用ant -buildfile <文件名>就可以了。
没有指定任何参数时,Ant会在当前目录下查询build.xml文件。如果找到了就用该文件作为buildfile。如果使用-find选项。Ant就会在上级目录中寻找buildfile,直至到达文件系统的根。要想让Ant使用其他的buildfile,可以用参数-buildfile file,这里file指定了你想使用的buildfile。

可以指定执行一个或多个target。当省略target时,Ant使用标签的default属性所指定的target。

命令行选项总结。

 ant [options] [target [target2 [target3] ...]]
Options:
-help print this message
-projecthelp print project help information
-version print the version information and exit
-quiet be extra quiet
-verbose be extra verbose
-debug print debugging information
-emacs produce logging information without adornments
-logfile file use given file for log output
-logger classname the class that is to perform logging
-listener classname add an instance of class as a project listener
-buildfile file use specified buildfile
-find file search for buildfile towards the root of the
filesystem and use the first one found
-Dproperty=value set property to value

实例:

使用当前目录下的build.xml运行Ant,执行缺省的target。

 ant

使用当前目录下的test.xml运行Ant,执行缺省的target。

 ant -buildfile test.xml 

使用当前目录下的test.xml运行Ant,执行一个叫做dist的target。

ant -buildfile test.xml dist

使用当前目录下的test.xml运行Ant,执行一个叫做dist的target,并设定build属性的值为build/classes。

ant -buildfile test.xml -Dbuild=build/classes dist
【责任编辑:夏书 TEL:(010)68476606】

9.2  项目中Ant的使用

9.2.1  build.xml


 

<?xml version="1.0"?>
<project name="Acesys" default="deploy-db">

<!-- properies -->
<property file="build.properties" />
<property name="src.dir" value="${basedir}/src" />
<property name="report.dir" value="${basedir}/report" />
<property name="lib.dir" value="${basedir}/lib" />
<property name="dist.dir" value="${basedir}/dist" />
<property name="doc.dir" value="${basedir}/doc" />
<property name="test.dir" value="${basedir}/test" />
<property name="target.dir" value="${basedir}/target" />
<property name="classes.dir" value="WebRoot/WEB-INF/classes" />
<property name="target.classes.dir" value="${target.dir}/classes" />
<property name="target.testclasses.dir" value="${target.dir}/test-classes" />
<property name="webroot.dir" value="${basedir}/WebRoot" />
<property name="db.dir" value="${basedir}/db" />
<!-- 定义classpath -->
<path id="master-classpath">
<fileset file="WebRoot/WEB-INF/lib/*.jar" />
<pathelement path="${webroot.dir}/WEB-INF/classes" />
</path>

<!--清除所有输出目录-->
<target name="clean" description="清空所有输出目录">
<echo message="清空所有输出目录"/>
<delete dir="${target.classes.dir}" />
<delete dir="${target.testclasses.dir}" />
<delete dir="${target.dir}" />
<delete dir="${dist.dir}" />
<delete dir="${doc.dir}" />
</target>
<!-- 初始化任务 -->
<target name="init" depends="clean">
</target>

<!-- 编译 -->
<target name="compile" depends="init" description="编译所有的java类">
<echo message="编译所有的java类"/>
<mkdir dir="${target.classes.dir}" />
<javac srcdir="${src.dir}" destdir="${target.classes.dir}" target= "1.5">
<classpath refid="master-classpath" />
</javac>
</target>

<!-- 测试   -->
<target name="test" depends="compile" description="进行单元测试">
<mkdir dir="${report.dir}"/>
<junit printsummary="on"
haltonfailure="false"
failureproperty="tests.failed"
showoutput="true">
<classpath refid="master-classpath" />
<formatter type="plain"/>
<batchtest todir="${report.dir}">
<fileset dir="${classes.dir}">
<include name="**/*Test.*"/>
</fileset>
</batchtest>
</junit>
<fail if="tests.failed">
***********************************************************
****       存在一个或多个错误 ,请检查错误  ......           ****
***********************************************************
</fail>
</target>


<!--打包成jar -->
<target name="pack" depends="compile" description="打jar包">
<echo message="生成ascent-acesys.jar"/>
<mkdir dir="${dist.dir}" />
<jar destfile="${dist.dir}/ascent-acesys.jar" basedir="${classes. dir}">
<exclude name="**/*Test.*" />
<exclude name="**/Test*.*" />
</jar>
</target>

<!-- Web应用打成war包 -->
<target name="war" depends="pack" description="打war包">
<echo message="生成acesys.war"/>
<mkdir dir="${dist.dir}" />
<jar destfile="${dist.dir}/acesys.war" basedir="${webroot.dir}">
<exclude name="**/*Test.*" />
<exclude name="**/Test*.*" />
</jar>
</target>

<!-- 部署到tomcat webapps目录下-->
<target name="deploy-war" depends="war" description="部署到tomcat webapps目录下">
<echo message="部署acesys.war到tomcat的webapps下"/>
<copy  todir="${tomcat.dir}/webapps" overwrite="true" >
<fileset dir="${dist.dir}">
<include name="acesys.war"/>
</fileset>
</copy>
</target>

<!-- 部署mysql数据库文件 -->
<target name="deploy-db" depends="deploy-war" description="初始化mysql数据库">
<echo message="部署数据库文件到mysql的data目录下"/>
<copy todir="${mysql.dir}/data" overwrite="ture">
<fileset dir="${db.dir}">
<include name="**/*.*" />
</fileset>
</copy>
</target>
<!-- 输出api文档 -->
<target name="doc" depends="compile" description="创建api文档">
<mkdir dir="${doc.dir}" />
<javadoc destdir="${doc.dir}" author="true" version="true" use= "true" windowtitle="AscentWeb API">
<packageset dir="${src.dir}" defaultexcludes="yes">
<include name="com/ascent/**" />
</packageset>
<doctitle>
<![CDATA[<h1>AscentWeb电子商务系统(Spring2.0+Hibernate3.1+Struts2.0)</h1>]]></doctitle>
<bottom>
<![CDATA[<i>Ascent Technologies,Inc,All Rights Reserved.</i>]]> </bottom>
<tag name="todo" scope="all" description="To do:" />
</javadoc>
</target>
</project>

【责任编辑:夏书 TEL:(010)68476606】


9.2.2  build.properties

项目中使用了外置属性文件build.properties(辅助build.xml的属性文件)。

mysql.dir=C:/Program Files/MySQL/MySQL Server 5.0
tomcat.dir=C:/Tomcat5.5

注:当在本地环境下使用Ant时,需要修改mysql.dir、tomcat.dir这些变量,让它们指向你自己环境下的路径
【责任编辑:夏书 TEL:(010)68476606】

9.3  Eclipse中使用Ant

Eclipse很好地集成了Ant,我们可以在Eclipse中编写和运行build.xml。

选择“Window→Preference”,可以看到Ant的配置,如图9-1所示。

 (点击查看大图)图9-1  Ant的配置

1.编辑build.xml

在Eclipse中建立一个build.xml文件,在Package Explorer中右键单击bookstoressh 项目,选择“New→ File”,在File Name框中填入build.xml,单击“Finish”按钮,将上面实例中的XML代码填入文件中并保存。Eclipse显然支持Ant。build.xml 在Package Explorer中左侧出现了一个Ant图标,而且Build文件的语法着色也发生了变化,XML声明用一个颜色,属性值用一个颜色,而Ant关键字用另一个颜色。Build文件的目标(targets)出现在右侧的OutLine视图中,如图9-2所示。

 (点击查看大图)图9-2  显示build.xml文件

2.运行Ant Build文件

在Eclipse中运行Build文件,有多种选择,下面介绍3种常用的。

① 可以在Package Explorer中右击build.xml,选择“Run As→ Ant Build”,如图9-3所示,这样来运行Ant,在Eclipse的控制台给出结果。

 (点击查看大图)图9-3  选择“Run As→Ant Build”② 可以在Package Explorer中右击build.xml,选择“Run→ Ant Build…”,如图9-4所示,进入配置页面。
 (点击查看大图)图9-4  选择“Run As→Ant Build…”配置Name:acesys build.xml,检查无误,单击下面的“Run”按钮运行Ant,在Eclipse的控制台给出结果,如图9-5所示。
 (点击查看大图)图9-5  运行build.xml的结果③ 选择“Window→Show View→Other…”如图9-6所示。
 (点击查看大图)图9-6  选择“Window→Show View→Other…”

在“Show View”对话框中选择“Ant→Ant”,如图9-7所示。

Eclipse会打开Ant视图窗口,如图9-8所示。

 (点击查看大图)图9-7  选择“Ant→Ant”  图9-8  Ant视图窗口

在此窗口中有按钮  ,可以选择添加Build文件,选择某个Target元素都可以执行上面的运行按钮或双击运行,运行整个Build文件,双击上面的文件名例如Acesys即可。

无论用哪种方式,运行结果都是一样的:

Buildfile: D:/jiaoxueli/myEclipse5.5_workspace/acesys/build.xml
clean:
[echo] 清空所有输出目录
[delete] Deleting directory
D:/jiaoxueli/myEclipse5.5_workspace/acesys/target/classes
[delete] Deleting directory
D:/jiaoxueli/myEclipse5.5_workspace/acesys/target
init:
compile:
[echo] 编译所有的java类
[mkdir] Created dir:
D:/jiaoxueli/myEclipse5.5_workspace/acesys/target/classes
[javac] Compiling 50 source files to
D:/jiaoxueli/myEclipse5.5_workspace/acesys/target/classes
[javac] 注意:某些输入文件使用了未经检查或不安全的操作。
[javac] 注意:要了解详细信息,请使用 -Xlint:unchecked 重新编译。
pack:
[echo] 生成ascent-acesys.jar
[mkdir] Created dir: D:/jiaoxueli/myEclipse5.5_workspace/acesys/dist
[jar] Building jar:
D:/jiaoxueli/myEclipse5.5_workspace/acesys/dist/ascent-acesys.jar
war:
[echo] 生成acesys.war
[jar] Building jar:
D:/jiaoxueli/myEclipse5.5_workspace/acesys/dist/acesys.war
deploy-war:
[echo] 部署acesys.war到tomcat的webapps下
[copy] Copying 1 file to C:/Tomcat5.5/webapps
deploy-db:
[echo] 部署数据库文件到mysql的data目录下
[copy] Copying 7 files to C:/Program Files/MySQL/MySQL Server 5.0/data
BUILD SUCCESSFUL
Total time: 15 seconds
【责任编辑:夏书 TEL:(010)68476606】