一、为啥要用Ant-Contrib ?
因为要做一个循环,用户配置两个或多个工程名后,这两个或多个工程有相同的工程结构,但是是属于不同的项目,如果把这个两个项目的工程整合成一个,写一个build,自动的把这几个工程进行合并。
看了一下ant,没有java中类似于下面代码的功能,所以找到Ant-Contrib,听说这个东东能帮我解决问题。
String array[]={"aa","bb","cc"};
for (int i = 0; i < array.length; i++) {
method(array[0]);//当然对于build来说,这里应该是target
}
二、开始使用
找到http://ant-contrib.sourceforge.net/,上面说得很清楚了,使用Ant-Contrib之前应该先安装ant,而且Ant-Contrib 中的大部分task需要ant1.5或者更高版本。先看一下我的ant版本,我用得是Eclipse中集成的1.6.5ant,"Window→Preferences→Ant→Runtime",如下图,在classpath中可以看到我的ant 版本是1.6.5。
先在网上下载一个ant-contrib-1.0b3.jar,我已经上传到附件中,
然后在ant的build.xml中添加下面的代码:
<?xml version="1.0" encoding="GBK"?> <!DOCTYPE project [ <!ENTITY build-properties SYSTEM "build-properties.xml"> ]> <project name="DCI.XXX" basedir="." default="build-many-project"> <!-- ============================================================== --> <!-- Compile Settings --> <!-- ============================================================== --> <property name="build.debug" value="on" /> <property name="build.debuglevel" value="lines,vars,source" /> <property name="build.optimize" value="off" /> <property name="build.deprecation" value="off" /> <property name="build.source" value="1.4" /> <property name="workspace.dir" location="../../../" /> <property name="target.project.dir" location="../../" /> <path id="ant.contrib.lib"> <fileset dir="lib"> <include name="**/*jar" /> </fileset> </path> <taskdef resource="net/sf/antcontrib/antcontrib.properties"> <classpath> <path refid="ant.contrib.lib" /> </classpath> </taskdef> <taskdef name="foreach" classname="net.sf.antcontrib.logic.ForEach"> <classpath> <path refid="ant.contrib.lib" /> </classpath> </taskdef> <!-- ============================================================== --> <!-- 循环构建每一个工程 --> <!-- ============================================================== --> <target name="build-many-project"> <foreach target="build-one-project" param="projectName" list="cip;hnppb_bap" delimiter=";" /> </target> <!-- ============================================================== --> <!-- 构建每一个工程 --> <!-- ============================================================== --> <target name="build-one-project"> <!--把java文件拷贝到src/java目录--> <copy todir="${target.project.dir}/src/java" overwrite="true"> <fileset dir="${workspace.dir}/${projectName}/src/java"> <include name="**/*" /> </fileset> </copy> </target> </project>
上面的代码可以看出,我只使用了foreach这个功能,还有if等别的功能,大家可以使用。
三、确实方便了很多,根据客户配置的工程名,处理每个工程,但是后来又遇到一个问题,就是copy时,因为是把两个或者多个工程合并到一个工程,我希望重名的文件能够给出提示,让用户手工处理,ant 的copy task太简单了,只能配置是否覆盖,所以我确定扩展ant,即自己定义task ,ant的架构设计得真是优秀,扩展起来太方便了,只需要建一个继承了Task类的类,打包成jar后,在xml配置文件中使用 taskdef 导入即可,具体来说就是以下几步:
1、建一个工程:
在Eclipse下的ant jar包拷到lib 下,设置build path, 这样就不会报编译错误。
2、构建BuildManyProject类
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
public class BuildManyProject extends Task {
public void execute() throws BuildException {
System.out.println("俺会输出来的");
}
}
3、打包为jar,将class文件拷到f盘,然后使用
cmd
f: (进入f盘)
jar -cvf buildmatic.jar com\ (打包为buildmatic.jar)
将buildmatic.jar拷贝到build.xml文件所以工程的lib目录下
4、使用:在 build.xml中加入下面的代码
<path id="ant.buildmatic.lib"> <fileset dir="lib"> <include name="**/buildmatic.jar" /> </fileset> </path> <taskdef name="buildManyProject" classname="com.smartdor.bap.buildmatic.BuildManyProject"> <classpath> <path refid="ant.buildmatic.lib" /> </classpath> </taskdef> <buildManyProject/>
OK,,运行的时候会出现:"俺会输出来的"
总结:ant 里定义了一结构建工程常用的命令,例如copy、javac等,ant-contrib对ant的任务进行了扩展,提供了条件、循环判断,但是如果有时候这些扩展还是不满足我们的日常需求,那只能自己扩展了,有必要研究一下ant 架构的设计,看看怎么做到这么灵活的可插拔的,end.