利用Ant实现项目自动构建测试备份并发布到项目web
转自:csdnblog beyondii
利用Ant实现项目自动构建测试备份并发布到项目web(1)
Ant是一个非常好的java编译工具。作者说这个东西是不带make缺陷的make工具(linux/unix用户对make/makefile应该是很熟悉了吧),这里我们来具体实践一下使用Ant进行项目构建管理。
文章开始,我也没有免了俗套,先简要的介绍一下Ant。Ant是一个java的基本构建工具(我这里使用构建这个词,是因为我觉得对于Ant来讲,编译只是其中很小的一部分)。Ant是使用java开发的,但不仅仅是一个只适用于java工具,也可以为其他语言提供相映的功能,就像其他的make工具一样。而且由于java是跨平台的,所以ant也是可以跨平台使用的,真正的实现了java的一次编写到处运行的。当前Ant已经推出了1.54版了,这个版本需要jdk1.1以上版本的支持。不过我没有具体试验过,一来jdk1.1找起来很不容易,二来也没有人会用这个低版本的jdk进行开发了,尤其在中国。
Ant需要用户自己编写一个build脚本来对项目进行管理。这个脚本是xml格式的文档(近来非常流行使用xml文档,至少我看到的apache.org上的java项目的配置文件都是xml格式了,看来我们也的与时俱进呀)。使用任何一种你喜欢的编辑器都可以编写这样的build脚本,如果你愿意当然可以使用windows自带的记事本来写,没有人会反对。我在这里使用的是eclipse。选择他的缘故是因为eclipse自身已经集成了Ant 1.5.3版本(作为eclipse的一个插件),可以很方便的使用,而且集成了Ant的编辑器,可以做到代码提示,最重要的原因是我的项目是用eclipse来开发的,所以eclipse是不二的选择。
在eclpise中是不需要配置Ant的如果你是在其他的环境中使用Ant那么需要配置相应的path和classpath,将你的ant_home下的lib文件夹加入classpath中,这里包含了ant的基本类包。将ant_home下的bin文件夹加入你的path中,这样就可以在windows终端窗口使用ant工具了。
Ant的执行是Ant [脚本文件]这种格式,如果没有指明脚本文件,那么ant会在当前文件夹下寻找build.xml文件作为当前的脚本文件,如果连这个也找不到就只好报错了。
当然在eclipse中是不用这么麻烦的。只要在eclipse中运行扩展工具里的run as中的ant build就可以了。Ant会自动去寻找当前项目文件夹中的build.xml的。并且以后就可以直接使用了。
基本知识介绍完毕,开始进入正题:Ant的build.xml的编写。下面以我的InterfacePackage项目的开发来进行build.xml的解说。
首先大家要记住build.xml是xml文档(好像是废话,因为文件的扩展名已经告诉我们答案了),所以所编写的build.xml必须遵守xml文档的规范,否则ant会毫不留情的报错(计算机就是这样,一点也不给人留面子,每次报错都是直截了当冷酷无情的)。
<!--这是申明,说明这确实是一个xml文档-- >
<?xml version="1.0" encoding="UTF-8" ?>
<!—这里说明了我的项目的文件名,default指定的是默认的task-- >
<project name="ConsoleViewer" default="dest">
这里我们基础到了几个ant的基本概念,就是每一个脚本都是由project段内的一些内容为主体的,通过project标签我们可以指定项目名,和默认的task。Task是ant中的一个最重要的概念,ant通过执行脚本中的一系列task来完成工作,所以task是可以说是ant的灵魂。
<property name="project.version.info" value="1.1.0" />
<property name="project.name.info" value="InterfacePackage" />
<property name="project.package.type.info" value="jar" />
<property name="project.encoding.info" value="UTF-8" />
<property name="base.dir" value="." />
<property name="src.dir" value="${base.dir}/src" />
<property name="bin.dir" value="${base.dir}/bin" />
<property name="dest.dir" value="${base.dir}/dest" />
<property name="doc.dir" value="${base.dir}/doc" />
<property name="code.dir" value="${base.dir}/code" />
<property name="lib.dir" value="${base.dir}/lib" />
<property name="bak.dir" value="${base.dir}/bak"/>
<property name="juit.report.dir" value="${base.dir}/JUnitReport" />
<property name="web.dir" value="E:/env/deploy/html/ibeyond/${project.name.info}" />
<property name="web.doc.dir" value="${web.dir}/doc" />
<property name="web.code.dir" value="${web.dir}/code" />
<property name="web.src.dir" value="${web.dir}/src" />
<property name="web.src.dir" value="${web.dir}/bin" />
<property name="web.old.dir" value="${web.dir}/old" />
<property name="web.bin.dir" value="${web.dir}/bin" />
<property name="web.report.dir" value="${web.dir}/test/report"/>
以上这些是我定义的一些property。何谓property呢?就是ant脚本的一些属性,而task就是ant脚本的方法,通过属性和方法的结合完成对象所能完成的工作,看来ant也是面向对象的。以上property我不需解释大家也肯定应该能看的懂吧.其中带info后缀的是指信息,带dir后缀的当然是指文件夹了。
利用Ant实现项目自动构建测试备份并发布到项目web(2)
<path id="appClassPath">
<pathelement path="${java.class.path}"/>
<fileset dir="${lib.dir}">
<include name="*.jar"/>
</fileset>
<fileset dir="${bin.dir}">
<include name="**/*.class"/>
</fileset>
</path>
先配置一下路径问题,因为是一个java项目,当然优先考虑的是classpath了。
<target name="init">
<tstamp />
<delete dir="${dest.dir}" />
<delete dir="${doc.dir}" />
<delete dir="${code.dir}" />
<delete dir="${bin.dir}" />
<mkdir dir="${base.dir}"/>
<mkdir dir="${bin.dir}"/>
<mkdir dir="${dest.dir}"/>
<mkdir dir="${doc.dir}"/>
<mkdir dir="${code.dir}"/>
<mkdir dir="${bak.dir}"/>
<mkdir dir="${juit.report.dir}"/>
<mkdir dir="${juit.report.dir}/xml"/>
<mkdir dir="${web.dir}"/>
<mkdir dir="${web.code.dir}"/>
<mkdir dir="${web.doc.dir}"/>
<mkdir dir="${web.old.dir}"/>
<mkdir dir="${web.src.dir}"/>
<mkdir dir="${web.bin.dir}"/>
<mkdir dir="${web.report.dir}"/>
</target>
首先进行初始化任务,看起来也很简单。就是清空一些文件夹然后建立一些文件夹,这个target就是task的集合,也就是说一个target可以执行多个task,也很容易理解为了完成一个目标当然有可以使用多个方法了,这里的delete和mkdir都是各自独立的task。我在第一行写了<stamp />这个声明,说他是声明是因为如果你想在你的build脚本中使用当前的时间日期的话就必须指定这个,然后在后文中就可以使用${DSTAMP}这样的标签了。
<target name="javadoc" depends="init">
<javadoc packagenames="*"
destdir="${doc.dir}"
sourcepath="${src.dir}"
charset="${project.encoding.info}"
encoding="${project.encoding.info}"
author="true"
version="true"
use="true"
splitindex="true"
windowtitle="${project.name.info} ${project.version.info} API Documentation">
<classpath refid="appClassPath" />
<doctitle>
<![CDATA[ <h1>${project.name} APIs(Version ${project.version})</h1> ]]>
</doctitle>
<bottom>
<![CDATA[ <div algin="center">Copyright © 2002-2003 www.ibeyond.org, All Rights Reserved.</div>]]>
</bottom>
<tag name="todo" scope="all" description="To do:" />
</javadoc>
</target>
第二个target,其中只有一个task就是javadoc,用来生成项目的api doc,基本上javadoc的参数都被ant支持了。所以你平时怎么用javadoc现在依然可以怎么用javadoc。合格target出现了一个新的关键字“depends”
也就是依赖,就是说如果要执行这个task那么就必须先运行他的“depends”在这里就是“init”,所以我写的这个build就像是文学中的倒叙似的。
利用Ant实现项目自动构建测试备份并发布到项目web(3)
<taskdef name="java2html" classname="com.java2html.Java2HTMLTask" />
<target name="javacode" depends="javadoc">
<java2html title="${project.name.info}version(${project.version.info}) Source Code Online View"
simple="no"
tabsize="4"
marginsize="2"
header="true"
footer="true"
encoding="UTF-8"
destination="${code.dir}">
<fileset dir="${src.dir}">
<include name="**/*.java"/>
</fileset>
<javadoc localRef="${doc.dir}" />
</java2html>
</target>
又来了一个新的关键字taskdef,这个是用来做什么的呢?听我慢慢道来。
古人云:“人无完人”,ant的开发者也是这样,他不可能预见到所有用户的需求,也就不能知道当前用户需要哪些task,肯定就会出现用户希望得到的task而ant默认没有支持的情况,所以ant的开发者提供了一个借口,可以让用户自定义自己的task,然后通过taskdef来声明(对要为开发者的这个想法击节叫好,用汤司令了一句名言“高,实在是高”),这样就实现了ant的无限扩展了。Taskdef至少要指明name和classname。Name用来指定这个task的任务的标签名,像javadoc这样的就是标签名(javadoc是ant内置的task),classpath就是这个标签名的要执行的类的方法名,关于这个扩展task的开发我会在其他文章中阐述的,这里就到此为止,大家心里有这个印象就可以了(java2html可以看出是一个把java代码转换成html文档的工具,我使用的是我的修改版,可以支持字符编码,详情见拙著的〈java2html改造手记〉系列文章,当前我已经开发了java2html的图形界面,同样我会另外撰文阐述)。
<target name="compile" depends="init">
<javac srcdir="${src.dir}"
destdir="${bin.dir}"
encoding="${project.encoding.info}"
debug="off"
optimize="on">
<classpath refid="appClassPath" />
</javac>
</target>
这个也很简单,就是一个编译。
<target name="junit" depends="compile">
<junit printsummary="yes" fork="yes" haltonfailure="no">
<classpath>
<pathelement location="${bin.dir}"/>
<pathelement path="${java.class.path}"/>
</classpath>
<formatter type="xml"/>
<batchtest todir="${juit.report.dir}/xml/${DSTAMP}">
<fileset dir="${bin.dir}">
<include name="**/*Test.class" />
</fileset>
</batchtest>
</junit>
<junitreport todir="${juit.report.dir}/xml/${DSTAMP}">
<fileset dir="${juit.report.dir}/xml/${DSTAMP}">
<include name="TEST-*.xml"/>
</fileset>
<report format="noframes" todir="${juit.report.dir}/html/${DSTAMP}"/>
</junitreport>
</target>
这是一个测试target。执行全部的测试代码,并把测试结果生成xml文档并将这个xml文档转换成html文档,junit也是ant默认支持的(java的开源社区的力量实在是太强大了,向广大的开源社区的同志们致敬)。
利用Ant实现项目自动构建测试备份并发布到项目web(4)
<target name="package" depends="junit">
<jar jarfile="${dest.dir}/${project.name.info}-${project.version.info}-N${DSTAMP}.${project.package.type.info}"
basedir="${bin.dir}" />
</target>
<target name="backup" depends="package">
<zip destfile="${bak.dir}/${project.name.info}-${project.version.info}-N${DSTAMP}.zip">
<zipfileset file="${base.dir}/build.xml" />
<zipfileset file="${dest.dir}/${project.name.info}-${project.version.info}-N${DSTAMP}.${project.package.type.info}" />
<zipfileset dir="${src.dir}" prefix="src/"/>
<zipfileset dir="${bin.dir}" prefix="bin/" />
<zipfileset dir="${doc.dir}" prefix="doc/" />
<zipfileset dir="${code.dir}" prefix="code/" />
<zipfileset dir="${lib.dir}" prefix="lib/" />
<zipfileset dir="${juit.report.dir}" prefix="JunitReport/"/>
</zip>
</target>
<target name="email" depends="backup">
</target>
以上内容是把应用打包备份等(jar/zip都是ant内置支持的)。Email这一段我使空着的,因为当前这个项目只有我一个人开发,所以我也不会给自己发email,如果你是一个团队开发异地开发,倒是可以利用这个将测试结果或者其他你想发的东西发送给你指定的人,而我的这个脚本要直接把开发结果发送到web上去,所以email功能对我来说也许是多余的。
<target name="dest" depends="email">
<copy todir="${web.code.dir}">
<fileset dir="${code.dir}" />
</copy>
<copy todir="${web.doc.dir}">
<fileset dir="${doc.dir}" />
</copy>
<copy todir="${web.old.dir}">
<fileset dir="${bak.dir}">
<include name="${project.name.info}-${project.version.info}-N${DSTAMP}.zip"/>
</fileset>
</copy>
<copy todir="${web.src.dir}">
<fileset dir="${src.dir}" />
</copy>
<copy todir="${web.report.dir}">
<fileset dir="${juit.report.dir}/html" />
</copy>
<copy todir="${web.bin.dir}">
<fileset dir="${dest.dir}">
<include name="${project.name.info}-${project.version.info}-N${DSTAMP}.${project.package.type.info}"/>
</fileset>
</copy>
</target>
将刚才生成的乱七八糟的东西copy到指定的地方去,完成部署,这样我的脚本就完成了。最后别忘了再脚本的最后面添加</project>,这样才符合xml文档的格式。
在这个脚本里我实现了项目Api文档的生成,在线java代码的生成,编译,测试,打包,备份,部署到web等,我个人觉得这个已经满足一般的项目需求了,当然你也可以根据以上内容进行扩充,例如利用ant对cvs的内置支持实现版本控制,或者每日构建等(每日构建可是微软的看家法宝,而且xp编程每日构建只是最低要求,以上纯是道听途说)。发挥你的想象力去重复利用ant给你带来的乐趣和成就感吧。
还是那句老话,没有你做不到,只有你想不到。
以上内容iBeyond版权所有(注ibeyond和beyondii是同一个人,从名字上就可以看出),你也许可以从www.ibeyond.org得到相关信息,也可以通过admin@ibeyond.org和我联系。