引言

Ant 脚本是由 Apache 提供的一种基于 Java 的构建工具,为 Java 开发人员所熟悉。Java 开发人员使用 Ant 脚本可以很方便地完成 Java 开发过程中常见的如拷贝文件、创建目录、编译、打包、压缩文件等等重复性的工作,从而提高开发效率,减轻开发人员负担,达到提高开发质量的目的。

Ant 既然是一种脚本语言,那么如何才能结构化设计 Ant 脚本, 从而使 Ant 脚本更易维护、更易扩展、更易重用,本文将就此目的做一些探讨。


回页首

使用 Ant generic target

在 Ant 中有 target(目标)和 task(任务)两个概念,一个 target 是 task 的容器,它可以包含一个或者多个任务,它们之间是一对多的关系。任务的例子有拷贝文件、创建目录等等。

在日常的开发过程中,经常会有一些经常重复的事情,对于这些事情我们可以定义一个 target 作为一个通用的 target,即 generic target, 它带有一些参数,这些参数由调用者在调用这个 generic target 时给定。别的 target 可以使用 antcall 任务去调用这个 generic target, 从而达到重用的目的。我们来看一个例子 , 比如说,调用一个 SQL 脚本文件,那么我们可以按照清单 1 构造一个 generic target:

清单 1. 调用 SQL 脚本的 run.sqlscript
 <target name="run.sqlscript">
<sql driver="${driver.name}" url="${jdbc.url}" userid="${user.name}"
password="${user.password}" expandProperties="true">
<classpath refid="deployment.lib" />
<transaction src="${sql.source}" />
</sql>
</target>

对于这个 Ant generic target run.sqlscript 我们看到它有下列参数:driver.name, jdbc.url, user.nameuser.password 及 sql.sourcedriver.name 指 JDBC 数据库驱动类的名字,例如对于 Oracle 数据库来说它叫 oracle.jdbc.driver.OracleDriverjdbc.url 是要连接的数据库的 URL,例如 jdbc:oracle:thin:@9.186.12.11:1521:XE,user.nameuser.password 分别是用户登陆名和密码,sql.source 是要调用的 SQL 脚本,<classpath refid="deployment.lib" /> 定义的类路径中包含对应数据库的 JDBC 驱动类包 , 请您参考清单 5。

那么如果要从一个 target 中调用这个 generic target, 那么我们可以按照清单 2 给出的例子来做:

清单 2. 调用 run.sqlscript 的 call.database
 <target name="call.database">
<antcall target="run.sqlscript">
<param name="driver.name" value=" oracle.jdbc.driver.OracleDriver"/>
<param name="jdbc.url" value=" jdbc:oracle:thin:@9.186.12.11:1521:XE"/>
<param name="user.name" value="test" />
<param name="user.password" value="test"/>
<param name="sql.source" value="${basedir}/../prj/oracle.sql" />
</antcall>
</target>

下面再看一个例子,例如我们要输出一条消息及这条消息输出时的时间,时间的格式可以按照用户的需求设定,那么我们可以按照清单 3 给出的例子写一个 generic target echo.time:

清单 3. 输出带有时间格式的消息的 echo.time
 <target name="echo.time">
<tstamp>
<format property="time" pattern="${time.pattern}" locale="${locale}"/>
</tstamp>
<echo>${message} at ${time}</echo>
</target>

这个 generic target echo.time 有三个参数,time.pattern,locale 和 message.time.pattern 指的是时间格式,如时间格式 yyyy/MM/dd hh:mm:ss:SS aalocale 即区域及语言设置,如 zh,CN,即中国中文,message 即是用户要输出的消息。我们可以按照清单 4 中的例子调用这个 generic target echo.time。

清单 4. 调用 echo.time
 <target name="call.echo.time">
<antcall target="echo.time">
<param name="time.pattern" value="yyyy/MM/dd hh:mm:ss:SS aa" />
<param name="locale" value="zh,CN" />
<param name="message" value="Begin deploy" />
</antcall>
<target>

回页首

组织 Ant generic targets

在使用 Ant generic targets 这个章节中演示两个例子后,我们来看如何组织这些 generic targets。 在面向对象的教程中经常会提到松耦合和内聚,松耦合即模块之间要减少依赖,内聚即实现类似功能的代码要放在一个模块中。按照这个原则我们可以把 generic target run.sqlscript 放在一个叫 Database.xml 的 XML 文件中,把 generic target echo.time放在一个叫 Util.xmlXML 文件中 , 如清单 5 和 6 所示:

清单 5. Database.xml 文件
 <?xml version="1.0" encoding="UTF-8"?> 

 <project name="database.generic">
<dirname property="proj.basedir" file="${ant.file.database.generic}"/> <path id="deployment.lib">
<fileset dir="${proj.basedir}/../Deployment/lib">
<include name="**.jar" />
</fileset>
</path> <target name="run.sqlscript">
<sql driver="${driver.name}" url="${jdbc.url}" userid="${user.name}"
password="${user.password}" expandProperties="true">
<classpath refid="deployment.lib" />
<transaction src="${sql.source}" />
</sql>
</target> </project>
清单 6. Util.xml 文件
 <?xml version="1.0" encoding="UTF-8"?> 

 <project name="util.generic">
<dirname property="proj.basedir" file="${ant.file.util.generic}"/> <target name="echo.time">
<tstamp>
<format property="time" pattern="${time.pattern}" locale="${locale}"/>
</tstamp>
<echo>${message} at ${time}</echo>
</target> </project>

在这两个文件 Database.xml 和 Util.xml 中,您可能注意到都有以 dirname 开头用黑体标注的一行 , 这一行非常重要,它定义了一个 property proj.basedir,property proj.basedir是用来储存 Database.xml 和 Util.xml 两文件所处的路径,从而使它们不用依赖于调用者就能够确定自己的所处的路径,进而消除和调用者之间的耦合。

那么如何调用在这两个文件中的 generic targets 呢?我们来看一个例子,假设我们把 Database.xml 和 Util.xml 放在目录 Scripts 下 , 那么整个结构如图 1 所示:

图 1. generic targets 调用结构示例

Build.xml 中我们需要导入文件 Database.xml 和 Util.xml,这样就可以在 Build.xml 里调用generic targets run.sqlscript 和 echo.time 了, 请参考清单 7

清单 7. Build.xml 文件
 <?xml version="1.0" encoding="UTF-8"?> 

 <project name="deployment">
<import file="${basedir}/Scripts/Database.xml" />
<import file="${basedir}/Scripts/Util.xml" />
</project>

总结

通过这样对 Ant 脚本的结构化设计,我们可以看出整个架构清晰,减少了耦合性,使得代码容易理解和维护,从而提高了重用性及开发效率。

http://www.cnblogs.com/iamhp/p/5756062.html

转: Ant 脚本的结构化设计的更多相关文章

  1. 利用ant脚本 自动构建svn增量/全量 系统程序升级包

    首先请允许我这样说,作为开发或测试,你一定要具备这种 本领.你可以手动打包.部署你的工程,但这不是最好的方法.最好的方式就是全自动化的方式.开发人员提交了代码后,可以自动构建.打包.部署到测试环境. ...

  2. [自动运维]ant脚本打包,上传文件到指定服务器,并部署

    1.根节点使用,表示根目录为当前目录,默认启动的target为build,项目名称为othersysm, <project basedir="." default=" ...

  3. 利用Ant脚本生成war包的详细步骤

    使用ant脚本前的准备 1.下载一个ant安装包.如:apache-ant-1.8.4-bin.zip.解压到E盘. 2.配置环境变量.新增ANT_HOME:E:\apache-ant-1.8.4:P ...

  4. ant脚本编写

    使用ant脚本前的准备 1.下载一个ant安装包.如:apache-ant-1.8.4-bin.zip.解压到E盘. 2.配置环境变量.新增ANT_HOME:E:\apache-ant-1.8.4:P ...

  5. Ant 脚本打印系统属性变量、ant内置属性

    Ant 脚本打印系统属性变量.ant内置属性 作用 编写ant脚本的时候,经常会引用到系统属性,本脚本用于打印系统常用属性(System.getProperties)与环境变量(Environment ...

  6. 关于项目既要使用ant脚本又要使用maven pom.xml文件的问题

    背景:项目使用的是ant脚本打包,但又需要maven去执行sonar代码扫描.所以项目中既有build.xml又有pom.xml build.xml设置的打包后产物文件夹为target,maven运行 ...

  7. 通过ant脚本编译打包android工程

    通过ant脚本,编译打包android工程 1.Android程序编译.打包.签名.发布的三种方式:  方式一:命令行手动编译打包  方式二:使用ant自动编译打包  方式三:使用eclipse+AD ...

  8. ant脚本

    jenkins在调用ant脚本时会遇到ant中的目标没有成功,但是最后的build状态却是success,如下图所示:代码中缺少一个},编译发生错误,最后的build成功. 解决方案:在关键的targ ...

  9. 运行ant脚本(转载)

    http://blog.csdn.net/linwei_1029/article/details/5809801 运行ANT脚本的步骤 1.右击我的电脑-->属性-->高级-->环境 ...

随机推荐

  1. 解决IOS下不支持fixed的问题

    我们公司有一个页面底部用到了fixed样式,每当弹出键盘的时候,IOS下fixed就会走样(据我所知android没有该问题). 为此之前我经过产品的同意做了简单的处理(方法1). 方法一: focu ...

  2. 邮件发送 java

    package com.sun.mail; import java.io.File;import java.io.IOException;import java.io.UnsupportedEncod ...

  3. 主题: jQuery异步调用KindEditor无法赋值【解决】

    KindEditor.ready(function (K) { window.editor1 = K.create('#tjssjs', { width: '480px', height: '150p ...

  4. JVM基础(4)-编译

    一.编译过程 不论是物理机还是虚拟机,大部分的程序代码从开始编译到最终转化成物理机的目标代码或虚拟机能执行的指令集之前,都会按照如下图所示的各个步骤进行: (其中绿色的模块可以选择性实现.) 很容易看 ...

  5. js刷新页面不回到顶部

    今天遇到刷新页面不回到顶部的需求 window.location.reload();方法已经解决了问题,但是ie8不支持,后来采用的是锚点这个方法 window.location = '/plan/g ...

  6. cmusphinx格式问题

    在windows下.lm和.dict同时为ANSI编码,输出正确,否则输出乱码或不输出结果.

  7. ZIP文件解压

    public class DZip { /// <summary> /// 压缩为ZIP文件 /// </summary> public void Zip(string dir ...

  8. JS中offsetTop、clientTop、scrollTop、offsetTop各属性介绍(转载)

    这里是JavaScript中制作滚动代码的常用属性 页可见区域宽: document.body.clientWidth;网页可见区域高: document.body.clientHeight;网页可见 ...

  9. CentOS 7 多网卡绑定

    根据官方文档Red_Hat_Enterprise_Linux-7-Networking_Guide-en-US用nmcli做起来还是相当容易的.下面把俺的步骤贴下. 1.查看目前网卡的名称和状态.#n ...

  10. URL匹配与req参数解析

    通配URL*(可代表任何字符串) 例如: app.get('/test/*', function(req, res){ res.send(req.query.aa); }) '/test/*通配tes ...