所有的语言都有维护和代码重用的压力,目前为止,Ant已经提供了很多的Task,可以帮助实现Ant脚本的模块化。
1. Property
Property Task除了能够定义单个的属性,还可以从一个属性定义文件定义多个property。把公用的属性放到属性文件中,各个build.xml中都载入此属性文件,就可以避免在每个build.xml中重复定义这些属性。
2. AntCall, Ant和SubAnt
AntCall可以理解为简单的函数调用。举一个例子就清楚了:
<target name=”commonTarget”>
<echo message=”${test.param}” />
</target>
<target name=”callingTarget”>
<antcall target="commonTarget">
<param name="test.param" value="Modulation" />
</antcall>
</target>
从上面的例子可以看到,指明要调用的target,再通过<param>指明调用参数;在被调用的Target中,通过与引用property类似的方式即可引用param的值。
至于Ant Target,也是调用别的Target,不过那个Target可以是在另外一个ant 文件中。
3. MacroDef
AntCall很好用,不过当参数很多时要写很多的<param name=”” value=”” />起来很麻烦,如果你想偷懒,用MacroDef就行了。下面把上面的例子用MacroDef重写:
<macrodef name="showModule">这里是macrodef的定义
<attribute name="test.param1"/>这个是参数的定义,可以再macrodef外部调用
<attribute name="test.param" default="NOT SET"/>内部参数
<sequential>实际执行的内容都在sequential中
<echo message="@{test.param}" />
</sequential>
</macrodef>
<target name="testMacro">
<showModule test.param="Modulation" />
</target>
需要注意的是:
1,在整个build文件里macrodef和target是平级的。
2,macrodef可以调用其他的macrodef,不可以调用target;target可以调用macrodef,也可以调用其他的target。
3,macrodef嵌套的时候,参数名称必须不同。
我们可以象系统提供的其他Task一样引用showModule,的确简洁多了。定义一个Macro,首先定义此宏的attribute,包括attribute的name, default;然后在<sequential>标签中定义此宏的所有操作。注意对attribute的引用是@{attr-name}!实际上,Ant还允许在attribute后面定义一组element,达到极高的动态性。
4. Import
<antcall>和<marcodef>可以达到类似函数的效果,但是调用者和被调用者还是必须在同一个文件中。Ant从1.6开始引入Import Task,可以真正的实现代码重用:属性,Task 定义,Task, Macro。一个简单的例子:
common.xml:
<?xml version="1.0" ?>
<project>
<property name="project.name" value="Ant Modulazation" />
<target name="commonTarget">
<echo message="${test.param}" />
</target>
<macrodef name="showModule">
<attribute name="test.param" default="NOT SET"/>
<sequential>
<echo message="@{test.param}" />
</sequential>
</macrodef>
</project>
call.xml:
<?xml version="1.0" ?>
<project name="testCommon" default="callingTarget">
<import file="common.xml" />
<target name="callingTarget">
<antcall target="commonTarget">
<param name="test.param" value="Modulation" />
</antcall>
</target>
<target name="testMacro">
<showModule test.param="Modulation" />
</target>
</project>
注意:在common.xml中,不能对project元素设置属性;另外,不要试图使用重名的property,或target以获取覆盖的效果,因为Ant毕竟不是编程语言。
自定义Ant Taskhttp://blog.csdn.net/pipisky2006/article/details/6680379
这里只有task,也可以创建project对象,写一个纯code的build
1:基本环境,建议用Eclipse这个工具来做为Java的基本开发工具,用Eclipse的向导新建一个Java工程test。
2:将ANT的以下几个jar文件添加到刚才新建的test工程的构建引用路径下面,即添加到classpath中去:ant-lanucher.jar、ant.jar、ant-jakarta-log4j.jar这三个jar文件是最基本的,必须添加进去,如果要用到ANT的一些其它类,需要添加相应的jar文件,具体可以参考ANT的帮助文件。这三个文件简单说明一下,ant-lanucher.jar里面的类是ANT程序启动时必须要用到的,在Java代码中调ANT时,是需要通过这个包中的类来启动ANT里面的类去执行定义的动作,这个包是启动入口类; ant.jar这个包里面是ant定义的一些核心功能类的class,如copy文件,删除文件,执行数据库脚本,打包等等,即是具体的核心功能实现类,如果是一些附加的ant功能,则在其它jar包里面,这个只有非常核心的类在里面; ant-jakarta-log4j.jar是ant重新包装了log4j的类,实现ANT自己格式的log4j的日志文件记录。
3:在test工程里面新建一个类,类里面增加一个Java的main方法,在main方法中添加如下代码,并导入相关的package:
PrintStream logstream = null; //这里是定义一个ANT执行时日志文件的输出流对象
Project pj=new Project(); //初始化一个ant的Project对象
pl.setName("ant_project"); //设置project的名称,具体的值可以随意改成其它字符串都可以
pj.init(); //ANT自己的方法初始化Project对象
DefaultLogger cl=new DefaultLogger();
//定义一个默认的日志流,默认的日志流是采用log4j来记录的,所以在前面要求将ant-jakarta-log4j.jar这个文件加到classpath中去。
logstream=new PrintStream(new FileOutputStream("C:/test.log"),true);
//下面两行是设置ANT执行过程中要输出的一些信息流,必须设置,否则后面将得不到具体的日志消息
cl.setErrorPrintStream(logstream);
cl.setOutputPrintStream(logstream);
//设置ANT记录日志的消息级别,MSG_VERBOSE是表示记录详细的日志消息
cl.setMessageOutputLevel(Project.MSG_VERBOSE);
//将前面定义好的消息记录器绑定到Project上
pj.addBuildListenter(cl);
//生成一个Target对象,为后面添加具体的Task做准备
Target tg=new Target();
tg.setProject(pj); //设置target的Project归属,必须设置,Target必须属于某一个Project
tg.setName("target1"); //设置Target的名称
pj.addTarget(tg); //将Target添加到Project中
Copy cp=new Copy(); //具体生成一个功能Task类对象,复制文件的对象
cp.setTodir(new File("C:/bbb")); //设置要将文件复制的目的地
FileSet set=new FileSet(); //定义目录集,这样在后面可以自己定义一些规则
set.setDir(new File("C:/aaa")); //定义目录集关联的实际目录路径
set.createInclude().setName("**/*.txt"); //设置这个目录集包括的规则,即这个目录下面所有的.txt后缀的文件
cp.addFileset(set); //将目录集绑定到具体的对象中
cp.setOverwrite(true);//设置在复制文件时,如果目标文件己经存在,将采用直接覆盖的方式
cp.setFailOnError(true); //设置在复制文件过程中有文件复制失败时,则中断执行这个过程
cp.setPreserveLastModified(true); //设置复制文件时保留文件的最后修改时间
cp.setProject(pj); //设置Task的Project归属
cp.setTaskName("cp"); //设置Task的名称
tg.addTask(cp); //将Task添加到Target中,Task不能单独存在,也不能直接添加到Project中
Throwable ta=null;
try {
pj.executeTarget(tg.getName()); //开始执行Project中指定的Target
}catch (Exception e){
ta=e;
} finally {
/* 在日志文件当中生成执行成功或失败的消息,调用这个方法后,如果ANT的Project执行成功,则会在日志文件当中生成一行“BUILD SUCCESSFUL”或"BUILD FAILED"这样的字符串,在执行失败时,同时会将异常消息打印在日志文件中,所以这个方法比较重要 */
pj.fireBuildFinished(ta);
logstream.close();
}
参考:http://www.wangchao.net.cn/bbsdetail_147308.html
http://hi.baidu.com/nlpack/blog/item/e101e327539177388644f906.html