内容


Ant 脚本的结构化设计

Comments

引言

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 调用结构示例
图 1. generic targets 调用结构示例
图 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 脚本的结构化设计,我们可以看出整个架构清晰,减少了耦合性,使得代码容易理解和维护,从而提高了重用性及开发效率。


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Java technology
ArticleID=791622
ArticleTitle=Ant 脚本的结构化设计
publish-date=02062012