这几天忙着看项目中的部分组件,各种坑的看不懂,所以先从最建单的项目打包看看。现在对于大型复杂的项目我觉得ant还是有一席之地的,虽然现在出去很多都是用的maven。下面是找的一个小的简要介绍,觉得写的不多,简单易懂:
转自:http://www.blogjava.net/dreamstone/archive/2006/09/20/70649.html
一,构建ant环境
要使用ant首先要构建一个ant环境,步骤很简单:
1),安装jdk,设置JAVA_HOME ,PATH ,CLASS_PATH(这些应该是看这篇文章的人应该知道的)
2),下载ant 地址www.apache.org找一个你喜欢的版本,或者干脆最新的版本
3),解压ant 你得到的是一个压缩包,解压缩它,并把它放在一个尽量简单的目录,例如D:\ant-1.6虽然你不一 定要这么做,但这么做是有好处的。
4),设置ANT_HOME PATH中添加ANT_HOME目录下的bin目录
5),测试一下你的设置,开始-->运行-->cmd进入命令行-->键入 ant 回车,如果看到
Buildfile: build.xml does not exist!
Build failed
那么恭喜你你已经完成ant的设置
二,体验ant
就像每个语言都有HelloWorld一样,一个最简单的应用能让人感受一下Ant
1,首先你要知道你要干什么,我现在想做的事情是:
编写一些程序
编译它们
把它打包成jar包
把他们放在应该放置的地方
运行它们
这里为了简单起见只写一个程序,就是HelloWorld.java程序代码如下:
package test.ant;
public class HelloWorld{
public static void main(String[] args){
System.out.println("Hello world1");
}
};
2,为了达到上边的目的,你可以手动的用javac 、copy 、jar、java来完成,但是考虑一下如果你有成百上千个类,在多次调试,部署的时候,一次次的javac 、copy、jar、java那将是一份辛苦的工作。现在看看ant怎么优雅的完成它们。
要运行ant需要有一个build.xml虽然不一定要叫这个名字,但是建议你这么做
下边就是一个完整的build.xml,然后我们来详细的解释每一句
<?xml version="1.0" encoding="UTF-8" ?>
<project name="HelloWorld" default="run" basedir=".">
<property name="src" value="src"/>
<property name="dest" value="classes"/>
<property name="hello_jar" value="hello1.jar"/>
<target name="init">
<mkdir dir="${dest}"/>
</target>
<target name="compile" depends="init">
<javac srcdir="${src}" destdir="${dest}"/>
</target>
<target name="build" depends="compile">
<jar jarfile="${hello_jar}" basedir="${dest}"/>
</target>
<target name="run" depends="build">
<java classname="test.ant.HelloWorld" classpath="${hello_jar}"/>
</target>
<target name="clean">
<delete dir="${dest}" />
<delete file="${hello_jar}" />
</target>
<target name="rerun" depends="clean,run">
<ant target="clean" />
<ant target="run" />
</target>
</project>
解释:
<?xml version="1.0" encoding="UTF-8" ?>
build.xml中的第一句话,没有实际的意义
<project name="HelloWorld" default="run" basedir=".">
</project>
ant的所有内容必须包含在这个里边,name是你给它取的名字,basedir故名思意就是工作的根目录 .代表当前目录。default代表默认要做的事情。
<property name="src" value="src"/>
类似程序中的变量,为什么这么做想一下变量的作用
<target name="compile" depends="init">
<javac srcdir="${src}" destdir="${dest}"/>
</target>
把你想做的每一件事情写成一个target ,它有一个名字,depends是它所依赖的target,在执行这个target 例如这里的compile之前ant会先检查init是否曾经被执行过,如果执行过则直接直接执行compile,如果没有则会先执行它依赖的target例如这里的init,然后在执行这个target
如我们的计划
编译:
<target name="compile" depends="init">
<javac srcdir="${src}" destdir="${dest}"/>
</target>
做jar包:
<target name="build" depends="compile">
<jar jarfile="${hello_jar}" basedir="${dest}"/>
</target>
运行:
<target name="run" depends="build">
<java classname="test.ant.HelloWorld" classpath="${hello_jar}"/>
</target>
为了不用拷贝,我们可以在最开始定义好目标文件夹,这样ant直接把结果就放在目标文件夹中了
新建文件夹:
<target name="init">
<mkdir dir="${dest}"/>
</target>
为了更多一点的功能体现,又加入了两个target
删除生成的文件
<target name="clean">
<delete dir="${dest}" />
<delete file="${hello_jar}" />
</target>
再次运行,这里显示了如何在一个target里边调用其他的target
<target name="rerun" depends="clean,run">
<ant target="clean" />
<ant target="run" />
</target>
好了,解释完成了,下边检验一下你的ant吧
新建一个src的文件夹,然后把HelloWorld.java按照包目录放进去
做好build.xml文件
在命令行下键入ant ,你会发现一个个任务都完成了。每次更改完代码只需要再次键入ant
有的时候我们可能并不想运行程序,只想执行这些步骤中的某一两个步骤,例如我只想重新部署而不想运行,键入
ant build
ant中的每一个任务都可以这样调用ant + target name
-----------------------------------------------------------------------------
这下面看看如何定制ant任务(task):
-----------------------------------------------------------------------------
转自:http://blog.sina.com.cn/s/blog_5c0522dd0100htlq.html
基础
ANT提供了非常丰富的批处理功能,几乎能完成在JAVA项目中所有的编译,整合打包工作,但有的时候仍有一些不能实现的功能或是不足,需要去自定义一些Task,以前写过一些Task,但没有系统的学习,今天好好地看了一下ANT的文档,整理了一下,写下来。
对于每个Task而言,其本身是一个JAVA类,有以下的规定
它必须有一个不带参数的构造方法
有一个void execute()方法,是Task的动作
我们现在做一个HelloWorld,代码如下:
任务对应的实现:
package ant.task;
/**
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 14-5-14
* Time: 下午10:41
* To change this template use File | Settings | File Templates.
*/
public class helloworld {
public void execute(){
System.out.println("你好...");
}
}
对应代码任务使用:
<?xml version="1.0" encoding="utf-8" ?>
<project name="anttask" default="jar" basedir=".">
<property name="dir.src" value="src" />
<property name="build.lib" value="lib"/>
<property name="build.out" value="target" />
<property name="build.classes" value="./${build.out}/classes" />
<property name="build.name" value="helloworld" />
<target name="prepare" description="环境初始化...">
<mkdir dir="${build.out}"/>
<mkdir dir="${build.classes}"/>
<mkdir dir="${build.classes}/${build.name}"/>
</target>
<target name="init" depends="prepare" description="任务初始化...">
<path id="build.classpath">
<fileset dir="${build.lib}" includes="*.jar"/>
<fileset dir="${build.out}" includes="*.jar"/>
</path>
</target>
<target name="clean" depends="init" description="清除target目录下的所有文件">
<delete failonerror="false" dir="${build.out}"/>
<mkdir dir="${build.out}"/>
<mkdir dir="${build.classes}"/>
<mkdir dir="${build.classes}/${build.name}"/>
</target>
<taskdef name="hello" classname="ant.task.helloworld">
<classpath>
<fileset dir="${build.lib}" includes="*.jar"/>
</classpath>
</taskdef>
<target name="compile" depends="clean" description="编译项目...">
<echo message="compile start...." />
<hello/>
<javac srcdir="${dir.src}" destdir="${build.classes}/${build.name}" debug="on" debuglevel="lines,vars,source" optimize="false" nowarn="true"
deprecation="false" failonerror="true" memoryInitialSize="256m" memoryMaximumSize="512m" fork="true" encoding="GB2312">
<classpath refid="build.classpath" />
</javac>
</target>
<target description="打包..." name="jar" depends="compile" >
<echo message="开始打包..."/>
<jar file="${build.out}/${build.name}.jar" basedir="${build.classes}/${build.name}">
<fileset dir="${build.classes}/${build.name}">
<include name="*.*"/>
</fileset>
</jar>
<echo message="打包完成..."/>
</target>
</project>
结果为:
引用
D:\workme\anttask>ant
Buildfile: D:\workme\anttask\build.xml
prepare:
init:
clean:
[delete] Deleting directory D:\workme\anttask\target
[mkdir] Created dir: D:\workme\anttask\target
[mkdir] Created dir: D:\workme\anttask\target\classes
[mkdir] Created dir: D:\workme\anttask\target\classes\helloworld
compile:
[echo] compile start....
[hello] 你好...
[javac] D:\workme\anttask\build.xml:41: warning: 'includeantruntime' was not
set, defaulting to build.sysclasspath=last; set to false for repeatable builds
[javac] Compiling 1 source file to D:\workme\anttask\target\classes\hellowor
ld
jar:
[echo] 开始打包...
[jar] Building jar: D:\workme\anttask\target\helloworld.jar
[echo] 打包完成...
BUILD SUCCESSFUL
Total time: 1 second
为了更好的被ANT支持,以及使用Project,Property等信息,Task最好从org.apache.tools.ant.Task继承,改写如下:
package ant.task;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
/**
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 14-5-14
* Time: 下午10:41
* To change this template use File | Settings | File Templates.
*/
public class helloworld extends Task {
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
private String message;
public void execute() throws BuildException{
System.out.println("你好..."+getMessage());
}
}
<?xml version="1.0" encoding="utf-8" ?>
<project name="anttask" default="jar" basedir=".">
<property name="dir.src" value="src" />
<property name="build.lib" value="lib"/>
<property name="build.out" value="target" />
<property name="build.classes" value="./${build.out}/classes" />
<property name="build.name" value="helloworld" />
<target name="prepare" description="环境初始化...">
<mkdir dir="${build.out}"/>
<mkdir dir="${build.classes}"/>
<mkdir dir="${build.classes}/${build.name}"/>
</target>
<target name="init" depends="prepare" description="任务初始化...">
<path id="build.classpath">
<fileset dir="${build.lib}" includes="*.jar"/>
<fileset dir="${build.out}" includes="*.jar"/>
</path>
</target>
<target name="clean" depends="init" description="清除target目录下的所有文件">
<delete failonerror="false" dir="${build.out}"/>
<mkdir dir="${build.out}"/>
<mkdir dir="${build.classes}"/>
<mkdir dir="${build.classes}/${build.name}"/>
</target>
<target name="compile" depends="clean" description="编译项目...">
<echo message="compile start...." />
<javac srcdir="${dir.src}" destdir="${build.classes}/${build.name}" debug="on" debuglevel="lines,vars,source" optimize="false" nowarn="true"
deprecation="false" failonerror="true" memoryInitialSize="256m" memoryMaximumSize="512m" fork="true" encoding="GB2312">
<classpath refid="build.classpath" />
</javac>
</target>
<target description="打包..." name="jar" depends="compile" >
<echo message="开始打包..."/>
<jar file="${build.out}/${build.name}.jar" basedir="${build.classes}/${build.name}">
<fileset dir="${build.classes}/${build.name}">
<include name="*.*"/>
</fileset>
</jar>
<echo message="打包完成..."/>
</target>
</project>
结果为:
引用
D:\workme\anttask>ant
Buildfile: D:\workme\anttask\build.xml
prepare:
init:
clean:
[delete] Deleting directory D:\workme\anttask\target
[mkdir] Created dir: D:\workme\anttask\target
[mkdir] Created dir: D:\workme\anttask\target\classes
[mkdir] Created dir: D:\workme\anttask\target\classes\helloworld
compile:
[echo] compile start....
[hello] 你好...Hello, xiej!
[hello] 你好...null
[javac] D:\workme\anttask\build.xml:41: warning: 'includeantruntime' was not
set, defaulting to build.sysclasspath=last; set to false for repeatable builds
[javac] Compiling 1 source file to D:\workme\anttask\target\classes\hellowor
ld
jar:
[echo] 开始打包...
[jar] Building jar: D:\workme\anttask\target\helloworld.jar
[echo] 打包完成...
BUILD SUCCESSFUL
Total time: 1 second
在配置中可以使用的类型不光是String,还可以是:
类型 接受值
boolean true,yes,no,false
char或java.lang.Charset 首字符
值类型(int,short等) 数值
java.io.File 文件路径名,当是一个相对路径时,按Project的baseDir计算文件名,取得其对应文件
org.apache.tools.ant.types.path 路径名,当是一个相对路径时,按Project的baseDir计算路径
java.lang.Class 类名,一个在classPath中能找到的类
有String做为参数的构造方法的类 构造方法参数
org.apache.tools.ant.types.EnumAttributes的子类
枚举名
调用
当我们的Task中用到了其他的Task时,方法如下:
构造相应的Task
调用其setProject方法
设置其配置值
执行perform()方法
Task容器
当一个Task的参数是一个Task的系列,就像Target一样时,需要使用Task容器。实现方法如下:
将Task实现org.apache.tools.ant.TaskContainer接口
实现接口中的void addTask(Task task)方法即可
例如,我们创建反复执行指定Task系列的循环Task,代码如下:
import java.util.List;
import java.util.ArrayList;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.TaskContainer;
public class Repeat extends Task implements TaskContainer {
private List taskList;
private int repeat;
public void setRepeat(int repeat) {
this.repeat = repeat;
}
public void init() throws BuildException {
taskList = new ArrayList();
}
public void addTask(Task task) {
taskList.add(task);
}
public void execute() throws BuildException {
for (int i = 0; i < repeat; i++) {
for (int j = 0; j < taskList.size(); j++) {
Task task = (Task) taskList.get(j);
task.perform();
}
}
}
}
编写build.xml,如下:
"test" depends="jar">
"./test.jar" name="Repeat" classname="Repeat"/>
"3">
"First"/>
"Second"/>
执行结果如下:
test:
[echo] First
[echo] Second
[echo] First
[echo] Second
[echo] First
[echo] Second
Property
Property除了在build.xml中可以定义之外,也可以在Task中读取和写入,Task需要实现setProject(Project project)和getProject()方法(如果从org.apache.tools.ant.Task继承,则已经实现)
Task可以通过getProject().getProperty(String)获取Property值,也可以通过getProject().setProperty(String key,String value)来设定Property值,如下面的Task向Property追加字符:
import org.apache.tools.ant.Task;
import org.apache.tools.ant.BuildException;
public class AppendProperty extends Task {
private String key;
private String append;
public void setKey(String key) {
this.key = key;
}
public void setAppend(String append) {
this.append = append;
}
public void execute() throws BuildException {
String orginal = getProject().getProperty(key);
String result;
if (orginal == null)
result = append;
else
result = orginal + append;
getProject().setProperty(key, result);
}
}
编写build.xml如下:
"test" depends="jar">
"./test.jar" name="AppendProperty" classname="AppendProperty"/>
"message" append="Property "/>
"${message}"/>
"message" append="Test"/>
"${message}"/>
执行结果如下:
test:
[echo] Property
[echo] Property Test
FileSet
FileSet是Ant中很常见的一种类型,它的使用方法参照以下程序:
import java.util.ArrayList;
import java.util.List;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.FileSet;
public class FileSetFind extends Task {
private List fileSetList;
public void init() throws BuildException {
fileSetList = new ArrayList();
}
public void addFileSet(FileSet fileSet) {
fileSetList.add(fileSet);
}
public void execute() throws BuildException {
for (int i = 0; i < fileSetList.size(); i++) {
FileSet fileSet = (FileSet) fileSetList.get(i);
DirectoryScanner ds = fileSet.getDirectoryScanner(getProject());
String[] includedFiles = ds.getIncludedFiles();
for (int j = 0; j < includedFiles.length; j++) {
String includedFile = includedFiles[j];
System.out.println(includedFile);
}
}
}
}
编写build.xml,如下:
"test" depends="jar">
"./test.jar" name="find" classname="FileSetFind"/>
"..">
"**/b/**"/>
执行结果如下:
test:
[find] AntTask\test\b\1.txt
[find] AntTask\test\b\2.txt
[find] AntTask\test\b\3.txt
其他的如Path,FileList使用方法相似,可参考相关的文档
异常
在前文的程序中一直出现一个org.apache.tools.ant.BuildException的类,一直没有说明,在这里说明一下,这是Ant专用的一个异常,Task执行中的异常应使用这个类,以便Ant或Ant工具进行处理
这里有一个例子:
import org.apache.tools.ant.Task;
import org.apache.tools.ant.BuildException;
public class Error extends Task {
public void execute() throws BuildException {
throw new BuildException("My Build Exception");
}
}
编写build.xml:
"test" depends="jar">
"./test.jar" name="error" classname="Error"/>
执行结果:
test:
BUILD FAILED
E:\workhome\AntTask\build.xml:23: My Build Exception