在项目开始编程的第一天就发布你的HelloWorld.
我们编写的程序最终需要发布,我的建议是在项目的第一天就建立好的你的发布脚步,在开发的过程中随时发布最新的进展到dev服务器上。每次项目会议时,demo演示环节,访问服务器而不是开发人员的本机。 保证每个项目的开发人员都可以一键发布,新加入的开发人员可快速在本机进行部署。
江南白衣在四种软件开发实践中建议每三个礼拜就发布一次。我认为在项目开发开始后,每个礼拜都进行软件的发布,每三个礼拜进行一次内部开发版本的增加(0.00 ~ 0.01)。每个开发人员都知道目前软件的全景,在进行软件feature 的brain storm时,非常清晰的界定哪些是已实现,哪些还是思维中孕育的云雾。基本上在一个feature的雏形出来后,下一个最重要的feature就跃然脑中了。往往你的头脑可以同时做两件事:当前feature的细节实现(coding),下一个feature的定义(requirements)。这种交替对你stuck时非常有益处。
Ant
如果你是c/c++程序员,相信你必然写过不少的make脚本。如果你是java程序,ant就是你必须掌握的第一个(如果你从notepad 下的helloworld开始)或者第二个工具(假如你从eclipse平台开始)。
Ant是什么?
Ant is a Java-based build tool. 主要完成以下三个任务:
-
编译
-
打包/发布
-
运行测试
为什么不直接使用javac来编译我的程序,然后使用jar来打包我的程序?
兄弟,想必你也了解任何一个非hello world的程序都会引用到许多的其他lib,任何一个web类的java程序在打包时都会有一大堆WEB-INF(页面,config,css,javascript)的文件。Ant就是来自动帮你来include lib引用,组织你的web app文件...
Hello Ant
任何一个hello world 类的 tutorial,包含以下四步:
-
Find a simple example
-
Try it
-
Have some basic concept
-
Know how to dig it more.
在学习踢球时,教练一般是先跟你示范,然后让你模仿,最后是跟你理论。同样,我们学习任何一个工具,框架,语言时,基本上遵守三步走的原则: color: #000000;">示范,模仿,理论。如果你悟性较高,就会有第四步:创新。学习的另外一个基本原则就是从整体到局部。假如你给一位老先生讲解汽车的结构,首先你拿出一个单独的轮子,告诉他汽车有四个这样的轮子,接着整出一单独的方向盘,随后又是一个单独的油罐,一单独的发动机,除非老先生是Karl Benz,否则他是断然不能从这些零件中组装拼凑出一个完整的汽车模样。
我们学习任何一样新的事物,第一件事情,总是Find a example and try it,有一个整体的认识后,对一个个局部的概念组件进行分解。废话略过,翠花,上hello, ant
Download
下载工具和文档
http://ant.apache.org/bindownload.cgi
注意下载最新的版本,阅读相应版本的文档(除非你找不到对应的文档)。ant的zip包里面已经包含有manual,所以不用另外下载。当然你也可以bookmark其manual文档网址http://ant.apache.org/manual/index.html
Install
- 解压到电脑任何一个有空间的地方,比如D:/apache-ant/ant-1.7
- 将ant的bin(D:/apache-ant/ant-1.7/bin)路径加入到path,(windows下:我的电脑 – 右键 property - 高级 – 环境变量)。习惯的做法是创建一个ANT_HOME的环境变量,指向ant目录(D:/apache-ant/ant-1.7),然后修改path为
path=%ANT_HOME%/bin;%PATH%
打开一个新的CMD窗口,输入 ant,验证是否设置成功。
如果提示你找不到build.xml,安装成功;如果提示没有ant这个命令,请google如何设置环境变量.
Try it
java 源文件 hello ant
build.xml文件
使用ant,就从build.xml文件开始。在CMD下面运行ant命令,默认会读入当前目录下build.xml文件,执行指定的target.
目录结构
-Myproject
-src
-Hello.java
-build.xml
使用ant命令,打开CMD,切换到Myproject目录,执行不同的task,观察CMD控制台输出和Myproject目录下新文件的生成
> ant
> ant clean
> ant init
> ant compile
> ant dist
麻雀虽小,可也五脏俱全。ant到底做了哪些事情?从build文件结构即可看出端倪:
变量定义properties: 如同java程序中,我们经常会抽取重复的字面常量为一个静态变量,以便修改,ant中的property的一个重要作用就是定义对字符串常量的引用,比如你可以将一个很长的路径定义为property
<property name=”long.path” value=””/>
在引用该路径时,只需要使用${long.path}即可。这样如果改路径修改为E:/xx/yy/zz,你只需要修改该property即可,而不用对所有使用到该路径的地方进行replace。Property另外一个重要的作用则对构建过程进行customize。比如我们在dev(开发), test(测试), prod(产品)中分别有不同的config文件(数据库的连接,不同的数据库服务器的ip),在打包时,我们希望生成的jar/war根据需要包含相应的config。这时我们可以使用${config.target},在执行ant命令时,通过-D参数选项来指定这个property值。
ant -Dconfig.target=prod
初始化 init: 生成build目录,编译过程中产生的class文件,放于在此目录
编译compile(javac): 将给定目录下(src)的所有java文件进行编译,指定目标目录为init中生成的build目录
打包 dist(jar): 将给定目录下(build)的class文件,打成jar包
清理clean:将构建中生成的一些临时目录删除
Ant Concept
project
熟悉XML文件的都知道,一个xml文件的node tree从一个根节点开始。build.xml 文件的根节点是project, 有三个很有用的属性
-
name – 可使用 ${ant.project.name} 来引用, 关于property,下文会进一步说明
-
default – 默认运行的target
-
basedir – build.xml 文件中所有相对路径的参考路径
target
官方文档: A target is a container of tasks that cooperate to reach a desired state during the build process
target对应我们构建过程中的一个环节, 编译,打包...。在ant中,则是task的容器(xml包含task子节点的父节点)。
我们在构建中,各个环会有先后依赖关系,要打包生成jar文件,首先需要编译生成class文件。Target的depends属性 制定依赖关系。例子中dist依赖于compile,compile依赖于init。
In a chain of dependencies stretching back from a given target such as D above, each target gets executed only once, even when more than one target depends on it.
两个最基本的属性
-
name
-
depends
task
官方文档: A task is a piece of code that can be executed.
Ant不过是脚本, 真正做事情的是什么呢? 编译,jdk bin下面的 javac; 生成目录,bat的mkdir命令... ant中的task则是调用这些命令的接口。Ant 的build-in task 很多,最常用的以下5种
property
最简单的property就是一变量,有两个最基本的属性
- name
- value
比如,<property name="foo.dist" value="dist"/>, 然后可使用${foo.dist}引用
你可以从properties文件里一次引入多个property,<property file="foo.properties"/> 还可以引入环境变量 <property environment="env"/> <echo message="ANT_HOME is set to = ${env.ANT_HOME}"/> 此外,ant 还有一些内建的property
Build_in_property: 使用频率最高的当是前面提到的${ant.project.name} 和 ${basedir}
path like structures
在我使用ant的初期,最常用而又最迷糊的就是path 类的结构。
我们编译时候,往往需要classpath,来包含给类的依赖jar包;在打包文件时,往往需要指定哪些文件需要被包含。
这正是path/classpath 用武之地。
例子
定义一个path结构,在javac中使用classpathref来应用这个path,从而指定依赖的jar包
下面例子中包含${lib.dir}目录下所有的jar包(包括子目录中的jar)
注意,ref引用时不需要${}来引用, path 中可以通过refid嵌套另外一个path,通过refid来引用另外一个path也是直接使用名称即可
也可以直接嵌套classpath,不过我们为了复用,往往另外定义path
从上面的例子中可以看出,path类结构有以下几种写法
- pathelement
- 指定location属性,指向单个文件或目录
- 指定path属性, 以; 或 : 分隔的多个location, 或者引用另外一个path
- 使用refid 进行嵌套 (或者classpathref 属性进行引用)
- 包含resouces colloection,其中最常用的当属于FileSet,通常我们指定一个dir,通过include和exclude来选出我们要包含的文件
<include name="**/*.java"/> <exclude name="**/*Test*"/>
模式pattern,经常用到两种,*
和
**。我们都知道*表示匹配任意的character(包括空)。ant中是进行path匹配,因此考虑嵌套结构(子目录):
单个*,则指对一层目录(per-directory)结构进行匹配,
两个**,则表示0层或者多层目录结构,
test/* 只匹配 test目录下的文件, such as test/x.java, test/y.html, but not test/foo/bar/xyz.html
test/** 匹配所有嵌套目录(子目录), such as
test/x.java
, or test/foo/bar/xyz.html
, but not /xyz.xml
.
Reference
(如有雷同,纯属拷贝):
http://ant.apache.org/manual/tutorial-HelloWorldWithAnt.html
http://ant.apache.org/manual/tutorial-writing-tasks.html
How to dig it more ?
本人也尚在dig之中,但以为要想dig more,无非以下几种
-
practice more 更多的练习
-
use it more 更多的使用。我们经常说用english来思考,用java来思考,同样的,用ant进行思考。换一种说法,真正的运用它来帮助你解决实际的问题。如果你在开发中总是重复的做一件事情,比如将生成的war包拷贝到Tomcat的webapp目录下来测试最新的代码,这时就该想想使用ant来自动化copy。老赵说他说c++,几次下来都没有坚持到底。我有同感,学校上机考试用的都是c++,可工作后从没有使用c++,现在也忘得差不多了。为什么? c++难吗?非也,未用而已。如果在某人的简历上写着精通c/c++,java,delphi, python, php, ruby, perl, javascript,...十多种语言,一定要问问这些语言是否解决过实际的问题,是否有真正的生产力。如果仅仅是hello world和toy,一天通一门非难事。
-
read more ant build file in open source project。外行看热闹,内行看门道。优秀的开源项目不仅是源代码一流,build文件和文档往往也是一流。
-
go through the manual。1), 2), 3)是点滴的经验积累,要想通盘掌握,了然于胸,go through是必不可少的环节。同样的,在熟悉掌握一个框架时,go through 所有的class和API也是你自己挖掘隐藏属性的好方法。
-
summary。本文也是summary之作...
-
jump out of ant: other tools, maven。