Groovy高效编程——用Gant替代Ant(更新于2008.02.18)
Ant的威力在Java界无人不知,无人不晓。可惜想在Ant的build.xml中处理逻辑很不方便,幸好在Groovy界出现了Gant(Groovy + Ant),使我们能够像写普通程序那样编写脚本。本文讲解了如何将您所拥有的Ant知识应用到Gant中,并利用Gant大大提高开发效率。
0,安装Groovy( Groovy轻松入门——搭建Groovy开发环境 )
1, 下载Gant, 访问http://gant.codehaus.org (目前最新版的下载地址:http://dist.codehaus.org/gant/distributions/gant-1.1.0_groovy-1.5.2.zip,该版本依赖Groovy1.5.2+)
2,安装Gant,将zip文件中的bin目录和lib目录中的文件分别解压到%GROOVY_HOME%\bin和 %GROOVY_HOME%\lib下
3,验证是否安装成功,打开命令行,运行‘gant’(命令本身不带‘’),如果您看到“Cannot open file build.gant”那就说明您安装成功了
4,小试牛刀,新建GantTest目录,在新建的GantTest目录下再新建build.gant和build.properties,并将下面的build.gant和build.properties内容分别复制到您刚刚新建的文件中,保存。在GantTest目录下运行‘gant’命令,运行结果如下所示:
D:\_DEV\groovy_apps\GantTest>gant
[echo] running build.gant
[echo] Executing init target
[echo] hello, Daniel
D:\_DEV\groovy_apps\GantTest>
[echo] running build.gant
[echo] Executing init target
[echo] hello, Daniel
D:\_DEV\groovy_apps\GantTest>
build.gant
Ant.echo(message :
'
running build.gant
'
)
Ant.property(file : ' build.properties ' )
def antProperty = Ant.project.properties
target(init : ' init target ' ) {
echo(message : ' Executing init target ' )
}
target(hello : ' say hello target ' ) {
depends(init)
echo(message : antProperty. ' echo.msg ' )
}
setDefaultTarget(hello)
Ant.property(file : ' build.properties ' )
def antProperty = Ant.project.properties
target(init : ' init target ' ) {
echo(message : ' Executing init target ' )
}
target(hello : ' say hello target ' ) {
depends(init)
echo(message : antProperty. ' echo.msg ' )
}
setDefaultTarget(hello)
build.properties
echo.msg=hello, Daniel
与build.gant等同的build.xml如下所示
<?
xml version="1.0" encoding="UTF-8"
?>
< project name ="test" default ="hello" >
< echo message ="running build.xml which is equivalent to build.gant" />
< property file ="build.properties" />
< target name ="init" description ="init target" >
< echo message ="Executing init target" />
</ target >
< target name ="hello" depends ="init" description ="say hello target" >
< echo message ="${echo.msg}" />
</ target >
</ project >
顺便提一下,我将build.gant,
build.properties,build.xml三个文件放于同一目录下
< project name ="test" default ="hello" >
< echo message ="running build.xml which is equivalent to build.gant" />
< property file ="build.properties" />
< target name ="init" description ="init target" >
< echo message ="Executing init target" />
</ target >
< target name ="hello" depends ="init" description ="say hello target" >
< echo message ="${echo.msg}" />
</ target >
</ project >
在Gant中调用Ant中的task是很简单的,只要将元素名改为方法名,将属性名和属性值改写为方法的参数名和参数方法,子元素改写为子闭包(改写子元素稍后进行讲解)即可。以上述例子为例,< echo message ="Executing init target..."/>改写为 echo( message : 'Executing init target...')。
下面一个例子展现了如何在Gant的脚本中表达逻辑,如你所看到那样,与平常所写代码并无两样:
Ant.echo(message :
'
running build.gant
'
)
Ant.property(file : ' build.properties ' )
def antProperty = Ant.project.properties
target(init : ' init target ' ) {
echo(message : ' Executing init target ' )
}
target(hello : ' say hello target ' ) {
depends(init)
// echo(message : antProperty.'echo.msg')
int alt = new Random().nextInt( 3 )
if ( 0 == alt) {
echo(message : ' hello world ' )
} else if ( 1 == alt) {
echo(message : ' hello gant ' )
} else {
echo(message : ' hello Daniel ' )
}
}
setDefaultTarget(hello)
Ant.property(file : ' build.properties ' )
def antProperty = Ant.project.properties
target(init : ' init target ' ) {
echo(message : ' Executing init target ' )
}
target(hello : ' say hello target ' ) {
depends(init)
// echo(message : antProperty.'echo.msg')
int alt = new Random().nextInt( 3 )
if ( 0 == alt) {
echo(message : ' hello world ' )
} else if ( 1 == alt) {
echo(message : ' hello gant ' )
} else {
echo(message : ' hello Daniel ' )
}
}
setDefaultTarget(hello)
我们也可以将一些常用的target放在一些文件中,需要时将它们引入:
比如我将常用的target放在了build.ext.gant中
target(ext :
'
ext target
'
) {
echo(message : " I'm an ext target " )
}
在需要的时候,我们通过includeTargets << new File('build.ext.gant')语句将其引入:
echo(message : " I'm an ext target " )
}
includeTargets
<<
new
File(
'
build.ext.gant
'
)
Ant.echo(message : ' running build.gant ' )
Ant.property(file : ' build.properties ' )
def antProperty = Ant.project.properties
def binDir = ' bin '
def srcDir = ' src '
target(init : ' init target ' ) {
echo(message : ' Executing init target ' )
delete(dir : " ${binDir} " )
mkdir(dir : " ${binDir} " )
copy (todir : " ${binDir} " ) {
fileset(dir : " ${srcDir} " ) {
include(name : " **/*.xml " )
}
}
}
target(hello : ' say hello target ' ) {
depends(init, ext)
// echo(message : antProperty.'echo.msg')
int alt = new Random().nextInt( 3 )
if ( 0 == alt) {
echo(message : ' hello world ' )
} else if ( 1 == alt) {
echo(message : ' hello gant ' )
} else {
echo(message : ' hello Daniel ' )
}
}
setDefaultTarget(hello)
Ant.echo(message : ' running build.gant ' )
Ant.property(file : ' build.properties ' )
def antProperty = Ant.project.properties
def binDir = ' bin '
def srcDir = ' src '
target(init : ' init target ' ) {
echo(message : ' Executing init target ' )
delete(dir : " ${binDir} " )
mkdir(dir : " ${binDir} " )
copy (todir : " ${binDir} " ) {
fileset(dir : " ${srcDir} " ) {
include(name : " **/*.xml " )
}
}
}
target(hello : ' say hello target ' ) {
depends(init, ext)
// echo(message : antProperty.'echo.msg')
int alt = new Random().nextInt( 3 )
if ( 0 == alt) {
echo(message : ' hello world ' )
} else if ( 1 == alt) {
echo(message : ' hello gant ' )
} else {
echo(message : ' hello Daniel ' )
}
}
setDefaultTarget(hello)
最后再看一下Gant调用Ant中包含子元素的task:
新建src和bin目录,在src目录下新建几个xml文件以作测试之用
Ant.echo(message :
'
running build.gant
'
)
Ant.property(file : ' build.properties ' )
def antProperty = Ant.project.properties
def binDir = ' bin '
def srcDir = ' src '
target(init : ' init target ' ) {
echo(message : ' Executing init target ' )
delete(dir : " ${binDir} " )
mkdir(dir : " ${binDir} " )
copy (todir : " ${binDir} " ) {
fileset(dir : " ${srcDir} " ) {
include(name : " **/*.xml " )
}
}
}
target(hello : ' say hello target ' ) {
depends(init)
// echo(message : antProperty.'echo.msg')
int alt = new Random().nextInt( 3 )
if ( 0 == alt) {
echo(message : ' hello world ' )
} else if ( 1 == alt) {
echo(message : ' hello gant ' )
} else {
echo(message : ' hello Daniel ' )
}
}
setDefaultTarget(hello)
Ant.property(file : ' build.properties ' )
def antProperty = Ant.project.properties
def binDir = ' bin '
def srcDir = ' src '
target(init : ' init target ' ) {
echo(message : ' Executing init target ' )
delete(dir : " ${binDir} " )
mkdir(dir : " ${binDir} " )
copy (todir : " ${binDir} " ) {
fileset(dir : " ${srcDir} " ) {
include(name : " **/*.xml " )
}
}
}
target(hello : ' say hello target ' ) {
depends(init)
// echo(message : antProperty.'echo.msg')
int alt = new Random().nextInt( 3 )
if ( 0 == alt) {
echo(message : ' hello world ' )
} else if ( 1 == alt) {
echo(message : ' hello gant ' )
} else {
echo(message : ' hello Daniel ' )
}
}
setDefaultTarget(hello)
如你所看到的,上面例子中的
delete(dir :
"
${binDir}
"
)
mkdir(dir : " ${binDir} " )
copy (todir : " ${binDir} " ) {
fileset(dir : " ${srcDir} " ) {
include(name : " **/*.xml " )
}
}
改写自
mkdir(dir : " ${binDir} " )
copy (todir : " ${binDir} " ) {
fileset(dir : " ${srcDir} " ) {
include(name : " **/*.xml " )
}
}
<
delete
dir
="${binDir}"
/>
< mkdir dir ="${binDir}" />
< copy todir ="${binDir}" >
< fileset dir ="${srcDir}" >
< include name ="**/*.xml" />
</ fileset >
</ copy >
< mkdir dir ="${binDir}" />
< copy todir ="${binDir}" >
< fileset dir ="${srcDir}" >
< include name ="**/*.xml" />
</ fileset >
</ copy >
改写过程很简单,仅仅是将子元素改写为子闭包就可以了。
请注意,build.gant本质上就是一个groovy程序,仅仅是文件后缀改为gant罢了,所以您可以将自己所有的Groovy知识应用到build.gant的编写中。
如果您想进一步学习研究Gant,请访问官方网站: http://gant.codehaus.org/
参考文献:
Groovy-power automated builds with Gant - Enhance your build process with Groovy plus Ant By Klaus P. Berg
附: 朝花夕拾——Groovy & Grails