ANT
Ant
是Apache开发的一个开源工具,他可以自动化很多事情。例如,他可以进行Java方面的自
动编译,打包,执行。也可以调用操作系统下的可执行程序。所以,从简单来说Ant的作用可以跟一个批处理文件类似,就是你可以定义连串的任务,然后敲一个命令,由系统帮你全部执行。当然Ant不止如此简单,因为,Ant的设计目标并不见得是为了替代批处理文件。
所以,如果要了解Ant的使用价值,我想就需要先了解什么叫极限编程(XP)。极限编程是一种软件方法学,他提倡“简单,沟通,鼓励,反馈”。从简单的角度来说,就是我们所作的设计应该尽可能的简单,不要添加太多额外的无用的功能,因为功能数正比于代码长度,和软件的复杂性。因此,简单的设计,就意味着简单易懂的代码,和更好的软件维护。至于反馈,在这里具有一个很广泛的含义,这主要看个人的理解了,这主要包括,用户的反馈,代码的反馈等。通过简单的设计,我们可以用更短的时间产生出软件的原型,从而更早的得到用户的反馈。而代码的反馈在我看来,更多是指单元测试的结果,当测试通过,则证明代码可以执行,从而我们可以进行进一步的重构,集成等更多的活动。至于,沟通和鼓励,更多的是从团队管理方面来提出设想。这里不再详述。
回到Ant的使用价值这个问题上,我想Ant的作用就是他可以提供一种很简单的方法来进行软件的持续集成和调试,更快的得到代码级的反馈。
<!--[if !supportLists]-->
2. <!--[endif]-->
Ant
使用
<!--[if !supportLists]-->
a) <!--[endif]-->
核心:Ant的使用核心是一个xml格式的build文件,用户可以根据自己的要求,定义Ant进行对应的操作。
<!--[if !supportLists]-->
b) <!--[endif]-->
结构:Ant的build文件,需要首先定义一个project标签,在同一个project下可以存在多个不同的target,而在任一个target内部可以存在多个不同的task。
<!--[if !supportLists]-->
c) <!--[endif]-->
例子:
<project name="test" default="all">
<target name="init">
…
</target>
<target name="clean" depends="init">
…
</target>
<target name="prepare" depends="init">
…
</target>
<target name="compile" depends="prepare">
…
</target>
<target name="all" depends="compile">
</target>
</project>
注:target之间可以是没有联系的,当然也可以通过depends属性使得target之间产生一定的依赖关系。
<!--[if !supportLists]-->
3. <!--[endif]-->
Ant
使用详解
<!--[if !supportLists]-->
a) <!--[endif]-->
项目定义:
<!--[if !supportLists]-->
i. <!--[endif]-->
语法:
<project name="" default=""></project>
<!--[if !supportLists]-->
1. <!--[endif]-->
name
:项目名称。
<!--[if !supportLists]-->
2. <!--[endif]-->
default
:默认执行的target。
<!--[if !supportLists]-->
ii. <!--[endif]-->
例子:
<project name="test" default="all"></project>
<!--[if !supportLists]-->
b) <!--[endif]-->
目标定义:
<!--[if !supportLists]-->
i. <!--[endif]-->
语法:
<target name="">
<!--[if !supportLists]-->
1. <!--[endif]-->
name
:目标名称。
<!--[if !supportLists]-->
ii. <!--[endif]-->
例子:
<target name="init">
<!--[if !supportLists]-->
iii. <!--[endif]-->
扩展:
<!--[if !supportLists]-->
1. <!--[endif]-->
依赖:
<target name="init"/>
<target name="prepare" depends="init"/>
注:prepare要执行,需要先执行init。
<!--[if !supportLists]-->
2. <!--[endif]-->
条件执行:
<target name="init" if="prop"/>
注:init要执行,当且仅当当前已定义了prop属性。
<target name="init" unless="prop"/>
注:init要执行,当且仅当当前没有定义prop属性。
<!--[if !supportLists]-->
c) <!--[endif]-->
属性定义:
<!--[if !supportLists]-->
i. <!--[endif]-->
语法:
<property name="" value="" />
<!--[if !supportLists]-->
1. <!--[endif]-->
name
:属性名。
<!--[if !supportLists]-->
2. <!--[endif]-->
value
:属性值。
<!--[if !supportLists]-->
ii. <!--[endif]-->
例子:
<property name="out.dir" value="E:/Java/Study/Test/Test" />
<!--[if !supportLists]-->
d) <!--[endif]-->
路径定义:
<!--[if !supportLists]-->
i. <!--[endif]-->
语法:
<pathelement path=""/>
path
的值是由“:”或“;”分割的多个文件。
<!--[if !supportLists]-->
ii. <!--[endif]-->
例子:
<pathelement path="a.jar:b.jar"/>
表示a.jar和b.jar两个文件。
<!--[if !supportLists]-->
iii. <!--[endif]-->
语法:
<pathelement location=""/>
location
的值是一个单独的文件或者目录。
<!--[if !supportLists]-->
iv. <!--[endif]-->
例子:
<pathelement location="a.jar"/>
表示a.jar一个文件。
<!--[if !supportLists]-->
v. <!--[endif]-->
语法:
<fileset dir=""/>
表示由dir所指定的文件夹下的所有文件。
<!--[if !supportLists]-->
vi. <!--[endif]-->
例子:
<fileset dir="c:/">
<include name="*test*.*"/>
</fileset>
表示c:/目录下所有文件名当中包含test的文件。除了include以外,我们还能使用其他的exclude,date,depth,size等子标记。除了fileset以外,还有其他类似的象dirset等。
<!--[if !supportLists]-->
e) <!--[endif]-->
任务定义:
任务是Ant的核心,因为用户所定义的Ant操作都是落实到任务上。
<!--[if !supportLists]-->
i. <!--[endif]-->
编译:
<!--[if !supportLists]-->
1. <!--[endif]-->
语法:
<javac srcdir="" destdir="">
<classpath>
<fileset>
</fileset>
</classpath>
</javac>
<!--[if !supportLists]-->
a) <!--[endif]-->
srcdir
:源目录。
<!--[if !supportLists]-->
b) <!--[endif]-->
destdir
:目标目录。
<!--[if !supportLists]-->
2. <!--[endif]-->
例子:
<javac srcdir="./src" destdir="./classes"/>
<!--[if !supportLists]-->
ii. <!--[endif]-->
压JAR包:
<!--[if !supportLists]-->
1. <!--[endif]-->
语法:
<jar basedir="" destfile="" manifest=""/>
<!--[if !supportLists]-->
a) <!--[endif]-->
basedir
:源目录。
<!--[if !supportLists]-->
b) <!--[endif]-->
destfile
:目标文件。
<!--[if !supportLists]-->
c) <!--[endif]-->
manifest
:MANIFEST.MF文件的位置。
<!--[if !supportLists]-->
2. <!--[endif]-->
例子:
<jar basedir="./classes" destfile="./test.jar" manifest="./MANIFEST.MF"/>
<!--[if !supportLists]-->
iii. <!--[endif]-->
压WAR包:
<!--[if !supportLists]-->
1. <!--[endif]-->
语法:
<war warfile="" webxml="">
<fileset dir="" />
<fileset dir="" />
<classes dir="" />
<lib dir=""/>
</war>
<!--[if !supportLists]-->
a) <!--[endif]-->
warfile
:目标文件。
<!--[if !supportLists]-->
b) <!--[endif]-->
webxml
:web.xml文件的位置。
<!--[if !supportLists]-->
2. <!--[endif]-->
例子:
<war warfile="${dist}/hello.war" webxml="${meta}/web.xml">
<fileset dir="./HTML" />
<fileset dir="./JSP" />
<fileset dir="${lib}" includes="helloapplet.jar" />
<classes dir="${build}" />
<lib dir="${lib}">
<exclude name="greet-ejbs.jar" />
<exclude name="helloapplet.jar" />
</lib>
</war>
<!--[if !supportLists]-->
iv. <!--[endif]-->
复制:
<!--[if !supportLists]-->
1. <!--[endif]-->
语法:<copy file="" todir="" />
<!--[if !supportLists]-->
a) <!--[endif]-->
file
:源文件。
<!--[if !supportLists]-->
b) <!--[endif]-->
todir
:目标文件夹。
<!--[if !supportLists]-->
2. <!--[endif]-->
例子:
<copy todir="./test" >
<fileset>
</fileset>
</copy>
<!--[if !supportLists]-->
4. <!--[endif]-->
Ant
与junit的集成
<!--[if !supportLists]-->
a) <!--[endif]-->
配置:需要把junit.jar放到Ant的lib目录下。
<!--[if !supportLists]-->
b) <!--[endif]-->
调用JUnit:
<!--[if !supportLists]-->
i. <!--[endif]-->
语法:
<junit printsummary="">
<formatter type="" usefile="" />
<test name="">
</test>
<classpath>
<pathelement location="" />
</classpath>
</junit>
<!--[if !supportLists]-->
1. <!--[endif]-->
printsummary
属性:是否打印结果。
<!--[if !supportLists]-->
2. <!--[endif]-->
formatter
标记:用于输出详细消息。type的类型可以为plain和xml等。usefile是指是否把输出结果输出到文件,默认为true。
<!--[if !supportLists]-->
3. <!--[endif]-->
test
标记:用于指定要调用的testcase。
<!--[if !supportLists]-->
4. <!--[endif]-->
classpath
标记:用于指定test标记中所指定的testcase的位置。
<!--[if !supportLists]-->
c) <!--[endif]-->
生成报告:当junit标记生成的文件为xml格式时,可以通过该标记把xml的结果通过xslt引擎转换为html文件。
<!--[if !supportLists]-->
i. <!--[endif]-->
语法:
<junitreport todir="">
<fileset dir="">
<include name=""/>
</fileset>
</junitreport>
<!--[if !supportLists]-->
1. <!--[endif]-->
todir
属性:指明文件的存储位置。
<!--[if !supportLists]-->
2. <!--[endif]-->
fileset
标签:指定要进行转换的文件位置。
<!--[if !supportLists]-->
d) <!--[endif]-->
完整例子:
<junit printsummary="true">
<formatter type="xml" usefile="true" />
<test name="nick.test.TestTest">
</test>
<classpath>
<pathelement location="./classes" />
</classpath>
</junit>
<junitreport todir="./report">
<fileset dir=".">
<include name="**/*TEST*"/>
</fileset>
</junitreport>
<!--[if !supportLists]-->
5. <!--[endif]-->
Ant
扩展
我们可以通过扩展Ant提供的接口,进行task的自定义。
<!--[if !supportLists]-->
a) <!--[endif]-->
简单任务(不包含属性和子元素)
代码:
public class HelloTask extends Task {
public void execute() {
System.out.println("Hello World");
}
}
build.xml
文件:
<taskdef name="mytask"
classname="nick.task.HelloTask"
classpath="./mytask.jar">
</taskdef>
<mytask />
注:taskdep标签用于把我们实现的类,与任务名mytask关联起来。
<!--[if !supportLists]-->
b) <!--[endif]-->
简单任务(只包含属性)
代码:
public class HelloTaskWithAttr extends Task {
private String name = null;
public void execute() {
System.out.println("Hello " + name);
}
public void setName(String name) {
this.name = name;
}
}
注:为了要为任务添加属性,需要在实现类当中提供对应的setter方法。
build.xml
文件:
<taskdef name="mytaskwithattr"
classname="nick.task.HelloTaskWithAttr"
classpath="./mytask.jar">
</taskdef>
<mytaskwithattr name="Nick" />
<!--[if !supportLists]-->
c) <!--[endif]-->
简单任务(包含子元素)
代码:
public class HelloTaskWithEle extends Task{
private Person p = null;
public void execute() {
System.out.println("Hello " + p.getName() + ". You are " + p.getAge()
+ " old.");
}
public Person createPerson() {
return new Person();
}
public void addConfiguredPerson(Person p) {
this.p = p;
}
}
public class Person {
private String name = null;
private int age = 0;
public Person() {
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
注:为了要包含子标记,首先要提供子标记的实现类。然后在实现类中提供两个方法,一个是
createXXX
方法( 上例中的createPerson()方法 )。另一个是addConfiguredXXX()( 上例中的addConfiguredPerson(Person p)方法 )。如果需要添加多个同样的子标签,则在addConfiguredXXX()方法中,通过集合类来保存所有这些子标记。
build.xml
文件:
<taskdef name="mytaskwithele"
classname="nick.task.HelloTaskWithEle"
classpath="${dist.dir}/mytask.jar">
</taskdef>
<mytaskwithele>
<person name="nick" age="24" />
</mytaskwithele>
<!--[if !supportLists]-->
d) <!--[endif]-->
复合任务(包含自任务)
代码:
public class HelloTaskWithEle extends Task implements TaskContainer {
private Person p = null;
private Task t = null;
public void execute() {
if (t != null)
t.perform();
System.out.println("Hello " + p.getName() + ". You are " + p.getAge()
+ " old.");
}
public Person createPerson() {
return new Person();
}
public void addConfiguredPerson(Person p) {
this.p = p;
}
public void addTask(Task t) {
this.t = t;
}
}
注:为了包含子任务,实现类需要实现TaskContainer接口,并且提供addTask(Task t)方法,
如果要限制一个任务所能包含的任务,则可以在addTask方法中进行过滤。要启动子任务时需要调用任务的perform()方法。
build.xml
文件:
<taskdef name="mytaskwithele"
classname="nick.task.HelloTaskWithEle"
classpath="${dist.dir}/mytask.jar">
</taskdef>
<mytaskwithele>
<person name="nick" age="24" />
<mytask />
</mytaskwithele>
<!--[if !supportLists]-->
6. <!--[endif]-->
总结:
这里只是对Ant的功能和特性进行一个简要的介绍和总结。在功能上,Ant除了能进行代码的编译和组装以外,还可以进行更多的,范围更广泛的应用。在工具集成方面,除了JUnit以外,Ant还可以与其他的,例如XDoclet等工具进行集成,以发挥更大的作用。