今天师父让我写个打包的脚本,我第一想到的就是Python,但是部门对shell和ant比较了解,为了脚本小工具的共享,就了解学习了经常听别人说起的ant,才发现之前做Java工程原来经常用到。下面进入正题:
一、ant环境的构建
1. 下载:很简单,从apache ant官网上下载ant,下载下来乍一看是tomcat,其实不然。然后又下载了几个包,这里需要描述下需求场景,需要从svn上检出一些文件,从服务器上下载一些jar包,然后按照一定的格式,打成tar.gz包,上传到服务器上。所以ant本身bin下的包不足以满足我们的需求。
因为需要从svn上检出一些我们需要的文件,所以用到了svn的包:svnant.jar, 当然还是其他比较好用的包,svnClientAdapter.jar, svnJavahl.jar, svnkit.jar, ganymed.jar,有兴趣的可以自行查找了解。
把下载好的svnant.jar放到ant的lib目录下。
2. 设置环境变量: 因为要用到ant命令,所以设置path到ant的bin目录即可; classpath到ant的lib目录即可。
二、ant初探面貌
简单来说,ant就是一堆xml文件,然后通过一些简单的命令执行xml文件,就可以实现一些很棒的功能。
这时候可能会想xml怎么能执行呢?平常了解的xml也就是做做配置文件, 然后就是Web数据的传输。
具体来说xml就是由project, target这样的标签,其中内嵌很多具体复制,删除等功能,然后target互相依赖,通过命令的调用,实现想要的功能。
所以平常工程中经常会见到build.xml,这就是一个工程利用ant的初步构建。
<?xml version="1.0" ?>
<project name="ant-project" default="print-dir" basedir=".">
<target name="print-dir">
<echo message="The base dir is: ${basedir}" />
</target>
</project>
三、SVN文件检出功能实现
1. 定义用到svn相关jar包的classpath:
<path id="classpath">
<pathelement location = "../../svnant.jar"/>
</path>
其实也可以不用写,因为已经设置了环境变量到ant的lib包下。
2. 引入svn.task文件,使用svn任务可以使用:
<typedef resource="org/tigris/subversion/svnant/svnatlib.xml" calsspathref="classpath"/>
3. 设置svn相关属性:
<svnSetting id="svn.setting" svnkit="true" username="jack" password="123" javahl="false" />
为了程序的可配置性,所以也可以写作:
<svnSetting id="svn.setting" svnkit="true" username="${svn.username}" password="${svn.password}" javahl="false" />
这里的svn.username 和 svn.password 写入 config.properties配置文件。然后只需要在调用执行命令时,把properties文件作为参数即可。
4. 检出文件代码:
<target name="checkout" depends="xxx">
<svn refid="svn.setting">
<checkout srcUrl="${svn.url}" destPath="${basedir}" force="true"/>
</svn>
</target>
这里svn.url也是写到config.properties文件中。
${basedir}是检出到的目录位置,是检出文件到的位置。
可以直接写在这个文件中,
其中checkout srcUrl=”${svn.url}” destPath=”.” force=”true” 中使用的是checkout,还有export;区别在于checkout会把svn相关的文件都检出,export只是检出最新的文件代码。
四、各类操作
1. 复制:
<!--todir:复制到的文件目录。-->
<!--force:是否通过timestamp来对target文件进行对比。默认为false -->
<!--failonerror:出错了是否终止程序。-->
<!--include是指哪些文件需要复制。*星号表示全部文件-->
<!--exclude是指哪些文件不需要复制。-->
<copy todir="${basedir}/.."> force="true" failonerror="true" >
<fileset dir="${xxx}">
<include name="xxx/xx.jar"/>
<exclude name="xxx/xx.txt">
</fileset>
</copy>
2. 剪切:
<move todir="${basedir}/.."> force="true" failonerror="true" >
<fileset dir="${xxx}">
<include name="*"/>
</fileset>
</move>
move的操作类似copy,不过是剪切复制
4. 删除:
<delete includeemptydirs="true", failonerror="true" >
<fileset dir="${xxx}" excludes="xxx/${outfile.tar.gz}">
</delete >
5. 新建文件夹:
<mkdir="xxx/xxx">
6. 宏:
出于打包功能的考虑,经常需要清理一个文件目录,然后再重新新建,所以借用了宏的功能。
宏可以理解成新建了一个新的操作标签,可以自己定义需要的属性。
根据这个功能,所以宏是这样写的:
<macrodef name="mkdir0">
<!--属性-->
<attribute name="dir"/>
<!--执行操作-->
<sequential>
<!--quiet:作用是指定当要被删除的文件或目录不存在时是否不显示提示信息。默认为false,代表要显示提示信息。-->
<delete quiet="true" dir="@{dir}" failonerror="false" />
<mkdir="@{dir}"/>
</sequential>
</macrodef>
然后使用宏:
<!--target就是每一个任务的标签 depends就是指这个任务依赖于哪个任务,从而从init的任务进行-->
<target name="clean" depends="init">
<!--echo 输出文本-->
<echo message="清理本地download目录">
<!--使用mkdir0宏-->
<mkdir0 dir="${basedir}/download"/>
<echo message="创建本地download目录成功"/>
</target>
7. 压缩
<!--创建tar destfile表示JAR文件名, basedir表示被归档的文件名。-->
<tar destfile="${basedir}/${download}/${outfile}.tar" basedir="${basedir}/${download}"/>
<!--创建tar.gz-->
<gzip destfile="${basedir}/${download}/${outfile}.tar.gz" src="${basedir}/${download}/${outfile}.tar">
<!-- 创建zip -->
<zip basedir="${basedir}/${download}" zipfile="${basedir}/${download}/${outfile}.zip"/>
<!-- 解压zip -->
<unzip src="${outfile}.zip" dest="extractDir"/>
8. 逻辑
<if>
<!-- 如果${outfile}和A一致-->
<equals arg1="${outfile}" arg2="A">
<!-- 那么-->
<then>
<!-- 解压-->
<unzip dest="${basedir}/A">
<!-- fileset是对文件的分组,而patternset是对模式的分组,-->
<patternset>
<incule name="xx/*.tar.gz"/>
</patternset>
<fileset dir="${basedir}/AA">
<include name="xx/*.zip"/>
</fileset>
</unzip>
<!-- 否则-->
<else>
<copy ....
<fileset dir="xx" include='xxx'/>
</copy>
</else>
</if>
9. 时间戳表示:
<tstamp>
<format property="version.date" pattern="yyyyMMdd" locale="en,GB"/>
</tstamp>
<property name="outfile", value="${module.prefix}_${module.name}_${version.date}">
这样导出的包命名就可以用时间戳表示,以便之后的比较。
五、run.bat
@echo off
set name=%1
echo ant程序开始
#带着config.properties和name等于A的参数运行aa.xml 不指定-f,默认执行build.xml
call ant -S -f aa.xml -propertyfile config.properties -Dname=A
#打开上传的文件目录
call explorer "..."
六、代码功能结构展示
实现本工具的需求,设计主要有三部分:
1. svn_check_out.xml:用于检出svn相关的文件代码到指定文件;
2. build_project.xml:用于整理文件目录等一系列操作,同时打tar.gz包;
3. upload.xml : 上传到服务器,如果在本地打好包,但由于网络问题,上传失败,可以执行带参数运行upload.xml;
4. run.bat:执行脚本;
时间太晚,过一阵子再帖上代码。