无所不能的Ant 【转】

.Ant简介:

       Ant----Another Neat Tool,是一个基于Java的跨平台构建工具,作为一个优秀的构建工具Ant有如下的优点:
Ø         语法简单,便于学习,如果你使用过XMl,就会更加感觉到这一点;
Ø         易于使用,可以减少基于Make方法的大型软件项目中编写makefile的人数;
Ø         跨平台,以一种灵巧的方式管理Java的classpath和文件的目录结构;
Ø         运行速度快,所有的Java都可以在Ant的JVM中启动;
Ø         与Junit测试框架紧密集成以实现极限编程的单元测试;
Ø         使用Java语言可以很容易的对他进行扩展;
Ø         内置对J2EE的开发的支持,如EJB的编译和打包等;
Ø         致力于解决Java项目的部署问题:如FTP,Telnet,应用服务器,SQL命令等,这些都可以自动部署.

 

 
Ant的官方网站: http://ant.apache.org/
Ant的最新版本:Ant 1.6.5
本文所有的例子运行的环境:JDK1.4.2,Ant1.6.2,eclipse3.0

 

 

.介绍AntDATATYPE和特性

       Ant的核心任务就是target,一个Ant文件有多个 target组成,而这些target之间,又有相互的依赖关系--depends,运行的时候默认运行project中指定的target.在构建一个 典型的Java工程时,多数的步骤用于处理文件和路径(如classpath),Ant提供的datatype可以很自然的处理这两个概念.文件集和路径 以及其他的几种类型的datatype,构成了Ant的构建文件的基本结构.

 

 

1.路径(Path

       在javac中我们经常使用的就是classpath,一个路径定义的例子如下:

                   <classpath>

                            <pathelement location =”lib/some.jar”/>

                   </classpath>

       location允许你指定单个的文件或者目录,也可以通过另一个路径莱扩展当前的路径,使用path来代替location:

                   <classpath>

                            <pathelement path =”build/classes;lib/some.jar”/>

                   </classpath>

       路径定义中元素间的分隔符可以使用分号,冒号,路径分隔符可以使用斜杠,反斜杠,不需要考虑操作系统的差异.

 

 

2.文件集(Fileset)

       所有的构建过程都会隐式的对一系列文件进行操作,Ant将文件集看成一种本地的datatype,下面看一个例子,这个例子是将文件从一个目录copy到另一个目录中:

                   <copy todir=”new_web”>

                            <fileset dir=”web”/>

                   </copy>

       在构建过程中我们通常需要包含或者排除一些文件,下面是一些典型的文件集示例:

                   <fileset>                                  

                            <include name="**/*Test.java"/>    

                   </fileset>    

            <fileset>

                            <exclude name="**/*.jsp"/>

                   </fileset>  

       默认情况下,include和exclude中的值是大小写敏感的,可以通过设置casesensitive=”false”,来取消它.
还有在许多情况下,IDE和代码管理系统会生成许多的临时文件,我们不得已要在每个文件集中去设置排除子句,为了避免这种情况,Ant针对这些特殊的模式的排除模式在默认情况下是激活的(例如:**/CVS,**/#*#等),详细模式可以查找相关的文档!.

 

 

3.模式集(Patternset)

       在文件集中使用Ant的另一个核心datatype:模式集,来实现包含和排除功能.模式匹配功能如下:
l       *  指代从零到任意长的字符.
l       ? 指代单一字符.
l       ** 作为目录名,代表目录树上从当前节电往下的所有目录,可以是零到任意多个目录.
l       以/ 或 /结尾的模式意味着结尾是**.
      

4.选择器(Selector)                              

       Ant1.5以上的版本包含了一个精密的新特性,选择器,他用来选择包含在文件集中的文件.介绍几种常用的内建选择器:
<filename>:基于模式匹配文件,工作方式类似与模式集的include或exclude元素
<size>:以小于,大于,等于该指定值为条件来选择文件.
<date>:以最后修改时间早于,迟于或等于指定值来选择文件.
<present>:选择存在于其他目录树的文件.
<contains>选择包含指定字符串的文件.
       这些选择器都可以被合并到选择器容器中以提供分组和逻辑表达,这些容器就是<and>,<or>,<not>,<none>和<majority>
       比较两个目录,并将只在一个目录下存在的文件复制到另一个目录下,我们来结合使用<not>和<present>

                   <copy todir="newfiles">

                            <fileset dir="web">

                                     <not>

                                               <present targetdir="currebtfiles"/>

                                     </not>

                            </fileset>

                   </copy>

       使用<contains>选择器,我们可以选择只包含特定字符串的文件:

                   <copy todir="newfiles">

                            <fileset dir="web">

                                     <contains text="System"/>

                            </fileset>

                   </copy>.

 

 
       这里简单提一下Ant的一个特性:Property,它与 java.util.Property在概念上非常相似,它允许在构建文件中自定义特性,并且允许将环境变量作为特性. Property具有特殊的权限,他可以在<target>之外执行,具体的用法,在下面将结合例子说明.

 

 
       以上介绍了几种Ant的常用datatype,Ant还包括很多的 datatype,例如过滤集(Filterset),过滤链(filterchain),过滤阅读器(FilterReader),Mapper映射 器,ZipFileset等等,可以通过相关资料来了解!
缺三
 

.使用Ant进行Junit测试

 

       我们除了使用java来直接运行junit之外,我们还可以使用junit提供的junit taskant结合来运行。涉及的几个主要的ant task如下:

l         <junit>,定义一个junit task

l         <batchtest>,位于<junit>中,运行多个TestCase

l         <test>,位于<junit>中,运行单个TestCase

l         <formatter>,位于<junit>中,定义一个测试结果输出格式

l         <junitreport>,定义一个junitreport task

l         <report>,位于<junitreport>中,输出一个junit report

 

       运行Junit需要jakarta-ant-1.4-optional.jar和Junit.jar包,因为这两个包用于支持ant task--<junit>的,所以不能在build.xml文件中加载,需要将他们放到ANT_HOME中去.使用eclipse可以按照一下步骤加入:

Windows-Preference-Ant-Runtime-Ant Home Entries

       下面看一个Junit测试的例子:

 

<?xml version="1.0"?>

 

<project name="project" default="junit">

 

         <property name="run.classpath" value="bin"></property>

 

         <property name="run.srcpath" value="src"></property>

 

         <property name="test.srcpath" value="test"></property>

 

         <property name="lib.dir" value="lib"/>    

 

        

 

         <path id="compile.path">

 

                   <pathelement location="${lib.dir}/junit-3.8.1.jar"/>

 

                   <pathelement location="${lib.dir}/log4j-1.2.8.jar"/>

 

         </path>

 

        

 

         <target name="compile">

 

                   <javac destdir="${run.classpath}" srcdir="${run.srcpath}"

 

                            classpathref="compile.path"/>

 

                   <javac destdir="${run.classpath}" srcdir="${test.srcpath}"

 

                            classpathref="compile.path"/>

 

         </target>

 

        

 

         <target name="junit" depends="compile">

 

                   <junit printsummary="true">

 

                            <classpath path="${run.classpath}"></classpath>

 

                            <test name="org.ant.test.Test1"></test>

 

                   </junit>

 

         </target>

 

</project>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

    可以看出Junit的使用基本和java差不多, printsummary允许输出junit信息,当然Ant提供formatter属性支持多样化的junit信息输出.Ant包含三种形式的formatter:

brief:以文本格式提供测试失败的详细内容;

plain:以文本格式提供测试失败的详细内容以及每个测试的运行统计;

xml:以xml格式提供扩展的详细内容,包括正在测试时的Ant特性,系统输出,以及每个测试用      例的系统错误.

       使用formatter时建议将printsummary关闭,因为他可能对formatter的生成结果产生影响,并多生成一份同样的输出.当然我们可以使用formatter将输出结果显示在console中:

<formatter type="brief" usefile="false"/>

 

Junit支持多个formatter同时存在:

<formatter type="brief" usefile="false"/>

 

<formatter type="xml"/>

 

使用xml我们可以得到扩展性更强的信息输出,这时在<test>中要设定todir来指定xml的输出路径.

       在通常情况下我们不可能一个一个来处理junit,所以Ant提供了<batchtest>,可以在他里面嵌套文件集(fileset)以包含全部的测试用例.

       对于大量的用例,使用控制台输出,或者使用文件或xml文件来作为测试结果都是不合适的,Ant提供了<junitreport>任务使用XSLT将xml文件转换为HTML报告.该任务首先将生成的XML文件整合成单一的XML文件,然后再对他进行转换,这个整合的文件默认情况下被命名为:TESTS-TestSuites.xml.

 

             <junitreport todir="${test.xml}">

 

               <fileset dir="${test.xml}">

 

                 <include name="TEST-*.xml"/>

 

               </fileset>

 

               <report format="frames" todir="${test.report}"/>

 

             </junitreport>

 

 

 

 

 

 

 

<report>元素指示转换过程中生成有框架(frames)或者无框架的类似与javadoc格式的文件,并保存到todir所在的目录下面.(由于xalan对于JDK1.4以上的版本存在问题,所以要生成HTML文件需要以下步骤:现在最新的xalan,在%JAVA_HOME%/jre/lib中建立文件夹endorsed.将xalan中的jar文件copy到里面).

 

下面看一个完整的例子:

 

 

            

 

<?xml version="1.0"?>

 

<projectname="project"default="junit">

 

    <propertyname="run.classpath"value="bin"></property>

 

    <propertyname="run.srcpath"value="src"></property>

 

    <propertyname="test.srcpath"value="test"></property>

 

    <propertyname="test.xml"value="xml"></property>

 

    <propertyname="test.report"value="report"></property>

 

    <propertyname="lib.dir"value="lib"/>

 

   

 

    <pathid="compile.path">

 

       <pathelementlocation="${lib.dir}/junit-3.8.1.jar"/>

 

       <pathelementlocation="${lib.dir}/log4j-1.2.8.jar"/>

 

    </path>

 

   

 

    <targetname="init">

 

       <deletedir="${test.report}"/>

 

       <mkdirdir="${test.report}"/>

 

       <deletedir="${test.xml}"/>

 

       <mkdirdir="${test.xml}"/>

 

    </target>

 

   

 

    <targetname="compile"depends="init">

 

       <javacdestdir="${run.classpath}"srcdir="${run.srcpath}"

 

           classpathref="compile.path"/>

 

       <javacdestdir="${run.classpath}"srcdir="${test.srcpath}"

 

           classpathref="compile.path"/>

 

    </target>

 

   

 

    <targetname="junit"depends="compile">

 

       <junitprintsummary="false">

 

           <classpathpath="${run.classpath}"></classpath>

 

           <formattertype="xml"/>

 

           <batchtesttodir="${test.xml}">

 

              <filesetdir="${run.classpath}">

 

                  <includename="**/Test*.class"/>

 

              </fileset>

 

           </batchtest>

 

       </junit>

 

      

 

        <junitreporttodir="${test.xml}">

 

          <filesetdir="${test.xml}">

 

            <includename="TEST-*.xml"/>

 

          </fileset>

 

          <reportformat="frames"todir="${test.report}"/>

 

        </junitreport>

 

    </target>

 

</project>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

<?xml version="1.0"?>

 

<projectname="project"default="junit">

 

    <propertyname="run.classpath"value="bin"></property>

 

    <propertyname="run.srcpath"value="src"></property>

 

    <propertyname="test.srcpath"value="test"></property>

 

    <propertyname="test.xml"value="xml"></property>

 

    <propertyname="test.report"value="report"></property>

 

    <propertyname="lib.dir"value="lib"/>

 

   

 

    <pathid="compile.path">

 

       <pathelementlocation="${lib.dir}/junit-3.8.1.jar"/>

 

       <pathelementlocation="${lib.dir}/log4j-1.2.8.jar"/>

 

    </path>

 

   

 

    <targetname="init">

 

       <deletedir="${test.report}"/>

 

       <mkdirdir="${test.report}"/>

 

       <deletedir="${test.xml}"/>

 

       <mkdirdir="${test.xml}"/>

 

    </target>

 

   

 

    <targetname="compile"depends="init">

 

       <javacdestdir="${run.classpath}"srcdir="${run.srcpath}"

 

           classpathref="compile.path"/>

 

       <javacdestdir="${run.classpath}"srcdir="${test.srcpath}"

 

           classpathref="compile.path"/>

 

    </target>

 

   

 

    <targetname="junit"depends="compile">

 

       <junitprintsummary="false">

 

           <classpathpath="${run.classpath}"></classpath>

 

           <formattertype="xml"/>

 

           <batchtesttodir="${test.xml}">

 

              <filesetdir="${run.classpath}">

 

                  <includename="**/Test*.class"/>

 

              </fileset>

 

           </batchtest>

 

       </junit>

 

      

 

        <junitreporttodir="${test.xml}">

 

          <filesetdir="${test.xml}">

 

            <includename="TEST-*.xml"/>

 

          </fileset>

 

          <reportformat="frames"todir="${test.report}"/>

 

        </junitreport>

 

    </target>

 

</project>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

生成的文档:

 

 

 

 

 

点击Properties超链接会弹出一个窗口显示在测试运行时全部的Ant特性,这对于跟踪由环境和配置造成的失败是非常便利的!

 

.使用Ant运行本地程序

1.使用Ant运行windows的批处理文件

 

       要在Ant内运行一个外部程序,应使用<exec>任务.它允许你执行下列操作:

l         指定程序名和要传入的参数.

l         命名运行目录.

l         使用failonerror标志来控制当应用程序失败时是否停止构建.

l         指定一个最大程序持续时间,时间超过则中止程序.任务在这时被认为是失败,但是至少构建会中止,而不是挂起,这对于自动构建是至关重要的.

l         将输出存到一个文件或特性.

l         指定java调用本地程序时需要预先设定的环境变量.

 

 

       下面来看一个例子:

批处理文件:

Test.bat

 

@echo off

 

echo Hello > test.txt

 

 

 

 

 

build.xml

 

<?xml version="1.0"?>

 

<project name="batch" default="extract" basedir=".">

 

    <target name="extract">

 

       <exec executable ="cmd">

 

           <arg line="/c a.bat"/>     

 

       </exec> 

 

    </target>

 

</project>

 

 

 

 

 

 

 

 

       使用executable元素标记指定使用的命令,具体用法可以在命令行下面输入help cmd查看.如果你希望在运行批处理发生错误时中止构建需要设定failonerror="on".加入你的外部程序在某个时刻挂起,也许是在与远程站点对话,而你不希望构建永远被挂起,Ant提供了timeout这个属性,他是一个以毫秒为单位的数字.下面看一下如何使用Ant来运行tomcat.

       启动tomcat需要两个环境变量CATALINA_HOME, JAVA_HOME,如果你在环境变量中已经设定,Ant中就不需要进行处理,如果没有需要使用<env>属性来设定,你也可以使用<env>属性覆盖你以前的环境变量.

 

 

 

<?xml version="1.0"?>

 

<projectname="batch"default="tomcat-start"basedir=".">

 

    <propertyname="tomcat.dir"value="C:/Tomcat5"></property>

 

   

 

    <targetname="tomcat-start">

 

    <execdir="${tomcat.dir}/bin"executable="cmd">

 

       <envkey="CATALINA_HOME"path="${tomcat.dir}"/>

 

       <argvalue="/C startup.bat"/>

 

    </exec>

 

    </target>

 

</project>

 

 

 

 

 

 

 

 

 

 

 

 

2.使用Ant运行shell文件

 

      由于windowsXPcmd默认没有安装ps,bash等命令,所以我们需要借助的三方的软件来实现这个功能,这里使用cgywin,cgywinbin目录加到环境变量的Path里面(下面使用Ant运行cvs也会用到).

 

 

<?xml version="1.0"?>

 

<projectname="batch"default="shell"basedir=".">

 

    <propertyname="tomcat.dir"value="C:/Tomcat5"></property>

 

   

 

    <targetname="shell">

 

    <execdir="${tomcat.dir}/bin"executable="bash">

 

       <envkey="CATALINA_HOME"path="${tomcat.dir}"/>

 

       <argvalue="startup.sh"/>

 

    </exec>

 

    </target>

 

</project>

 

 

 

 

 

 

 

 

 

 

 

3.使用Ant运行cvs

 

       Ant内置cvs属性,可以很方便的使用cvs:

 

 

<?xml version="1.0"?>

 

<projectname="batch"default="shell"basedir=".">

 

    <propertyname="cvs.root"value="..."></property>

 

   

 

    <targetname="cvs">

 

       <cvscvsroot="cvs.root"command="checkout ../.."/>

 

    </target>

 

</project>

 

 

 

 

 

 

 

 

如果你的Documents and Settings中有.cvspass文件,那么可以不用设定cvsroot,Ant会自动寻找.

 

 

 

.工程的打包部署

 

       工程的打包,主要就是文件的操作,下面通过例子简单介绍一下文件的移动,复制和删除.

 

 

<?xml version="1.0"?>

 

<projectname="project"default="jar">

 

    <targetname="copy">

 

       <tstamp>

 

           <formatproperty="time.format"                                           pattern="yyyy-mm-dd'T'HH:mm:ss"

 

              locale="en"/>

 

       </tstamp>

 

       <copytofile="dist/readme"file="test.txt">

 

           <filterset>

 

              <filtertoken="TIME"value="${time.format}"/>

 

           </filterset>

 

       </copy>

 

    </target>

 

 

 

    <targetname="move">

 

       <movetodir="dist">

 

           <filesetdir="lib">

 

              <includename="*.jar"/>

 

           </fileset>

 

       </move>   

 

    </target>

 

   

 

    <targetname="delete"depends="copy,move">

 

       <deleteverbose="true"failonerror="false">

 

           <filesetdir="dist">

 

              <includename="*.jar"/>

 

           </fileset>   

 

       </delete>

 

    </target>

 

</project>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

       需要说明的是文件删除的时候可能这个文件正在被别人是用而无法删除,所以要用failonerror来标记,文件的复制是时间戳敏感的,如果拷贝的文件比原文件要老,那么Ant将不会执行copy,解决的办法是将overwrite属性设置为true,由于移动文件是复制文件的一个子类,所以它们的原理基本相同.

 

      

 

       前面已经例举过一个jar文件打包的例子,下面主要介绍war文件的打包.Ant提供war文件打包的属性.<war>任务是<jar>任务的子类,但是他也提供了一些特有的属性:

 

 

 

    <targetname="deploy"depends="init">

 

           <wardestfile="${war.dir}/spring.war"webxml="${web.dir}/web.xml">

 

              <classesdir="${web.dir}/classes"></classes>

 

              <filesetdir="WebContent"excludes="web.xml"></fileset>

 

              <libdir="${web.dir}/lib"></lib>

 

           </war>

 

       </target>

 

 

 

 

 

 

 

 

 

 

 

可以看出war任务提供了许多WEB应用程序的特有属性,只要你指定了这些文件,war任务就会自动将他们放到正确的位置.

 

 

 

       部署是项目发布的过程,Ant支持FTP,Email,本地和远程等几种部署模式,但是Ant并不内置对一些部署的支持,需要第三方的库.

 

optional.jar            也可能是这样的名字:  jakarta-ant-1.4.1.optional.jar

 

netcomponents.jar       <ftp><telnet>需要

 

activation.jar                   <mail>需要

 

mail.jar                           <mail>需要

 

       下面只以本地部署为例,服务器为tomcat. 

 

       由于tomcat支持热部署,可以将webapp文件下的war文件自解压缩,所以最简单的部署方式是将工程打成war包后直接copywebapp目录下面.另一种方法是使用tomcat的管理员身份,manager页面装载和删除应用,这种方法比较复杂,也比较正规,他也是远程部署的基础.

 

 

 


<?xml version="1.0"?>


 


<project name="project" default="deploy-local-catalina">


 


    <property name="war.dir" value="dist"></property>


 


    <property name="web.dir" value="WebContent/WEB-INF"></property>


 


    <property name="webapp.name" value="spring"></property>


 


    <property name="catalina.port" value="8080"></property>


 


    <property name="catalina.username" value="admin"></property>


 


    <property name="catalina.password" value="admin"></property>


 


   


 


    <target name="init">


 


       <mkdir dir="${war.dir}"/>


 


    </target>


 


 


 


    <target name="mkwar" depends="init">


 


       <war destfile="${war.dir}/spring.war" webxml="${web.dir}/web.xml" >


 


           <classes dir="${web.dir}/classes"></classes>


 


           <fileset dir="WebContent" excludes="web.xml"></fileset>


 


           <lib dir="${web.dir}/lib"></lib>


 


       </war>


 


    </target>


 


   


 


    <target name="remove-local-catalina">


 


       <property name="deploy.local.remove.url"


 


           value="http://localhost:${catalina.port}/manager/remove"></property>


 


       <get dest="deploy.local.remove.txt"


 


           src="${deploy.local.remove.url}?path=/${webapp.name}"


 


           username="admin" password="admin"/>


 


      


 


       <loadfile property="depoly.local.remove.result"


 


           srcfile="depoly.local.remove.txt"></loadfile>


 


    </target>


 


   


 


    <target name="deploy-local-catalina" depends="mkwar, remove-local-catalina">


 


       <property name="deploy.local.urlpath"


 


           value="file:///D:/MyEclipse/workspace/springstruts/dist/spring.war"></property>


 


       <property name="deploy.local.url.params"


 


           value="path=/${webapp.name}&amp;war=${deploy.local.urlpath}"></property>


 


       <property name="deploy.local.url"


 


           value="http://localhost:${catalina.port}/manager/install"></property>


 


       <get src="${deploy.local.url}?${deploy.local.url.params}"


 


           dest="deploy-local.txt"


 


           username="admin"


 


           password="admin"/>


 


       <loadfile property="deploy.local.result"


 


           srcfile="deploy-local.txt"></loadfile>


 


    </target>


 


</project>


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 

可以看出只要将上面的localhost换成目标的ip地址就可以实现tomcat的远程部署

posted on 2013-03-01 14:34  箫轩  阅读(432)  评论(0编辑  收藏  举报

导航