Ant 笔记 2:运行一个 Java 程序
# Ant 笔记 2:运行一个 Java 程序
Ant 是根据构建脚本来执行的,构建脚本是 XML 文件,里面就是一个个 XML 元素。我们先介绍 2 个常用的。
# project
project 是构建脚本的根元素,所以一个构建脚本文件中必须包含且仅能包含一个 project 标签,<project>
和 </project>
之间所包含的所有内容组成了一个完整的构建文件。
project 元素的属性:
属性名 | 功能说明 | 缺省值 | 必须 |
---|---|---|---|
name | 当前构建文件的名称 | N | |
default | 当前构建文件默认的执行入口目标 | target | Y |
basedir | 当前构建文件(name)的基础路径 | 当前目录 | N |
description | 项目描述信息 | N |
# target
Ant 把构建分为了很多个目标,目标是一个或多个任务的集合。 任务就是具体的一段代码。
构建文件包含一个项目,在项目内部声明了所有目标。 要创建目标,可以使用 <target>
标记。
例如,一个构建文件里分了编译,打包和重启应用 3 个 target,每个 target 里有很多任务:
- target1:编译
- 任务 task1:创建目录用于存放 class 文件
- 任务 task2:编译 Java 文件
- ………
- target2:打包
- task1:打成一个 tar 或者 war 包
- task2:上传到服务器上
- ……
- target3:运行
- task1:停止应用
- task2:启动应用
- task3:检查应用状态
- …………
一个构建脚本里可以包含多个 target(任务元素),当然你也可以像第一个 Ant 项目那样不包含任务元素,但那样的话什么也做不了。target 拥有的属性
属性名 | 功能说明 | 缺省值 | 必须 |
---|---|---|---|
name | target 的名称 | Y | |
id | target 的 ID | N | |
depends | 依赖关系列表,是一个以逗号分隔的 <target> 元素名称列表 | N | |
if | 用于验证指定的属性是否存在 | N | |
unless | 用于验证指定的属性是否不存在 | N | |
description | 对当前目标任务 <target> 功能的一个简短描述 | N |
# 用 Ant 输出 HelloWorld
用 Ant 输出一句 HelloWorld。别看是输出一句 HelloWorld 而已,实际上在项目编译过程中输出一些关键的信息很有用的。
我们新建一个 1-HelloWorld.xml 文件,
- 增加第一个任务元素,名为:say hello。并通过 echo 元素打印出:hello world!
- 找到根元素,并添加 default 属性,属性值为:say hello,使 Ant 默认执行 say hello 任务;
- 完整代码如下:
<?xml version="1.0" encoding="GB2312"?>
<project name="demo" default="say hello">
<target name="say hello" description="你好,世界!">
<echo level="info" message="hello world!"/>
</target>
</project>
2
3
4
5
6
打开 cmd,进入构建脚本所在目录,运行:
D:\Projects\AntLearn> ant -file 1-HelloWorld.xml
Buildfile: D:\Projects\AntLearn\1-HelloWorld.xml
say hello:
[echo] Hello World!
BUILD SUCCESSFUL
Total time: 0 seconds
2
3
4
5
6
7
8
打印出:“hello world!”。这表示我们的第一个任务执行成功。
echo 就是具体的 task,后续我们会介绍一些常用的 task
请读者自己也动手完成这个例子,可以增加多几条打印语句。
# Ant 的属性
XML 文件中,一个标签可以有多个属性。
例如 project 标签,可以有 description 属性:
<project name="demo" description="Learn Ant project">
</project>
2
Apache Ant 属性类型有两种:
- 内置属性
- 用户定义的属性
Apache Ant 内置属性
Apache Ant 提供了各种内置属性,我们可以在构建文件中访问所有这些属性。 下面的表中给出了一些内置属性。
属性 | 描述 |
---|---|
basedir | 用于项目基础的绝对路径 |
ant.file | 用于构建文件的绝对路径 |
ant.version | 用于 Ant 的版本 |
ant.project.name | 它包含当前正在执行的项目的名称 |
ant.project.default-target | 它包含当前正在执行的项目的默认目标的名称 |
ant.project.invoked-targets | 调用当前项目时的目标列表 |
ant.java.version | 拥有的 JVM 版本 |
ant.core.lib | ant.jar 文件的绝对路径 |
ant.home | 包含 Ant 的主目录 |
ant.library.dir | 包含用于加载 Ant 的 jar 的目录。 |
Apache Ant 用户定义的属性
除了内置属性,Apache Ant 还提供了在 buildfile
中创建自定义属性的工具。
要创建属性,使用 Ant 提供的 <property>
标记,该标记使用 name
和 value
属性。 name
属性是属性的名称,value
属性包含的值。
# 用 Ant 输出属性
我们新建 一个文件 2-Property.xml,编写代码如下
<?xml version="1.0" encoding="UTF8"?>
<project default="echoProperty">
<property name="myName" value="Peter JXL"/>
<target name="echoProperty">
<echo>${myName} is my name. </echo>
</target>
</project>
2
3
4
5
6
7
运行:
PS D:\Projects\AntLearn> ant -file 2-Property.xml
Buildfile: D:\Projects\AntLearn\2-Property.xml
echoProperty:
[echo] Peter JXL is my name.
BUILD SUCCESSFUL
Total time: 0 seconds
2
3
4
5
6
7
8
属性之间可以嵌套,例如定义一个根目录,然后下面再定义几个子目录:
<property name="TEMP_DIR" value="./temp" />
<property name="TEMP_WEB_INF" value="${TEMP_DIR}/WEB-INF" />
<property name="TEMP_APP_LIB" value="${TEMP_WEB_INF}/lib" />
2
3
# 属性文件
当你只需要对小部分属性进行设置时,可以选择直接在构建文件中设置。然而,对于大项目,最好将设置属性的信息存储在一个独立的文件中。
存储属性信息在一个独立的文件中的好处:它可以让不同环境下重复使用相同的构建文件,但属性是不同的。例如测试环境和生产环境可能有部分配置不同,例如 IP 信息,文件的位置,版本等;因此可以创建多个不同的配置文件,一个文件对应一个环境,但构建文件不用修改,只用一个就行。
一般情况下,属性文件都被命名为 build.properties , 并且与 build.xml 存放在同一目录层。 你可以基于部署环境 ——比如: build.properties.dev 和 build.properties.test 创建多个 build.properties 文件。
在下面的例子中展示了 build.xml 文件和与之相联系的 build.properties 文件:
我们新建一个目录:3-properties
在里面新建一个 build.properties 文件
# The Site Name
sitename=www.peterjxl.com
buildversion=3.3.2
2
3
新建一个 build.xml
<?xml version="1.0"?>
<project default = "echoProperties">
<property file = "build.properties" />
<target name = "echoProperties">
<echo>Apache Ant version is ${ant.version} - You are at ${sitename} </echo>
</target>
</project>
2
3
4
5
6
7
运行:
D:\Projects\AntLearn\3-properties> ant
Buildfile: D:\Projects\AntLearn\3-properties\build.xml
echoProperties:
[echo] Apache Ant version is Apache Ant(TM) version 1.10.12 compiled on October 13 2021 - You are at www.peterjxl.com
BUILD SUCCESSFUL
Total time: 0 seconds
2
3
4
5
6
7
8
我们自定义了属性,并且使用了内置属性 ant.version
练习:请读者自己动手做一遍,并将本文提到的所有内置属性都打印出来。
# Ant 与文件
Ant 既然是用于构建的,总得和源代码打交道,这就得涉及到代码文件的路径,和代码文件集合。
在 Ant 中,这叫数据类型
# 文件集
代表了一个文件集合,用来包括或移除匹配某种模式的文件,可以理解为一个过滤器。举个例子:
<fileset dir="${src}" casesensitive="yes">
</fileset>
2
3
在上述代码中,src 属性指向项目的源代码文件夹。casesensitive 表明大小写敏感
有可能源代码目录中不是全都有用的,我们可以选择源代码文件夹中的 Java 代码,并且排除一些无用文件:
<fileset dir="${src}" casesensitive="yes">
<include name="/.java"/>
<exclude name="/Stub"/>
</fileset>
2
3
4
选择源文件夹中所有的 .java 文件,除了那些包含有 'Stub' 单词的文件,但 Samplestub.java 的文件将不会被排除在文件集之外(大小写敏感)
# 模式集合
我们可以用正则表达式,更具体的说明我们想要什么文件。我们先定义一个正则表达式
<patternset id="java.files.without.stubs">
<include name="src//.java"/>
<exclude name="src//Stub"/>
</patternset>
2
3
4
?
仅匹配一个字符*
匹配零个或者多个字符**
递归地匹配零个或者多个目录
文件集里使用这种正则表达式,用 ID 指定哪个正则表达式
<fileset dir="${src}" casesensitive="yes">
<patternset refid="java.files.without.stubs"/>
</fileset>
2
3
# 文件列表
文件列表数据类型与文件集相类似,除了以下几处不同:
- 文件列表包含明确命名的文件的列表,同时其不支持通配符。
- 文件列表数据类型能够被应用于现有的或者还不存在的文件中。
让我们来看一个下述的关于文件列表数据类型的例子。在这个例子中,属性 webapp.src.folder 指向该项目中的 Web 应用的源文件夹。
<filelist id="config.files" dir="${webapp.src.folder}">
<file name="applicationConfig.xml"/>
<file name="faces-config.xml"/>
<file name="web.xml"/>
<file name="portlet.xml"/>
</filelist>
2
3
4
5
6
还有很多描述文件的数据类型,暂且不表,后面我们会教如何看官方文档
# Task
# 再谈 target
我们之前说过,Ant 把构建分为了一个个目标,每个目标元素都可以包含一系列你想要执行的事务的集合。
例如,我们之前创建了一个 target,用来打印一句 HelloWorld。我们还可以在这个 target 里编译代码,运行代码,一个 target 里可以有很多 task
任务可以具有多个属性,每个任务都具有共同的结构。 常见结构由任务名称,属性等组成:
<task-name attribute1 = "value1" attribute2 = "value2" ... >
...
</task-name>
2
3
Apache Ant 任务分为两类:
- 内置任务
- 用户定义的任务,用的较少
# depends 属性
在实际开发过程中,我们可能有多个任务:例如一个任务用来编译,一个任务用来打包,一个用来删除中间文件……
同时,任务之间是有先后顺序的,例如要运行项目肯定得先编译,我们可以用 depend 属性说明哪个先执行。
举个栗子:
<target name="run" depends="compile">
...
</target>
<target name="compile">
...
</target>
2
3
4
5
6
7
调用顺序: 编译(compile)-> 运行(run),表示目标执行的顺序。
当然,也可以不指定 depend,在命令行里指定执行哪个 target。
> ant compile //只执行编译
> ant run //会执行编译和运行,因为run依赖于compile
2
# Ant 预定义(内置)任务
Apache Ant 本身在其库中提供的任务称为内置任务。 Apache ant 提供了大量内置任务, 如下列表所示:
- 存档任务
- 审计任务
- 编译任务
- 执行任务
- 文件任务
- 记录任务
- 邮件任务
- ..........................
# 存档任务
用于压缩和解压缩数据的任务称为归档任务。下面列出了一些常见的内置存档任务。
任务名称 | 描述 |
---|---|
Ear | Jar 任务的扩展,对文件进行特殊处理 |
Jar | 一组文件 |
Tar | 创建 tar 存档 |
Unjar | 解压缩 jar 文件 |
Untar | 解压 tarfile |
Unwar | 解压缩 warfile |
Unzip | 解压缩 zip 文件 |
War | Jar 任务的扩展 |
# 审计任务
任务名称 | 描述 |
---|---|
JDepend | 它用于调用 JDepend 解析器 |
# 编译任务
用于编译源文件的任务称为编译任务,下面列出了一些常见的内置编译任务。
任务名称 | 描述 |
---|---|
Depend | 确定哪些类文件的资源已过期 |
Javac | 编译源文件 |
JspC | 运行 JSP 编译器 |
NetRexxC | 编译 NetRexx 源文件 |
Rmic | 运行 rmic 编译器 |
# 执行任务
用于执行运行应用程序的任务称为执行任务。下面列出了一些常见的内置执行任务。
任务名称 | 描述 |
---|---|
Ant | 在指定的构建文件上运行 Ant |
AntCall | 在同一个构建文件中运行另一个目标 |
Apply | 执行系统命令 |
Java | 执行 Java 类 |
Parallel | 可包含其他 ant 任务的容器任务 |
Sleep | 按指定的时间暂停执行 |
# 文件任务
与句柄文件操作相关的任务称为文件任务。下面列出了一些常见的内置文件任务。
任务名称 | 描述 |
---|---|
Chmod | 更改文件的权限 |
Chown | 更改文件的所有权 |
Concat | 连接多个文件 |
Copy | 将文件复制到新目的地 |
Delete | 删除文件 |
Mkdir | 创建一个目录 |
练习:这里给出一段代码,请读者自行运行每个 target。源码目录:4-Target/build.xml
<?xml version="1.0" encoding="UTF8"?>
<project>
<target name="testMkdir">
<mkdir dir="test"/>
</target>
<!-- 运行前:先创建test目录 -->
<target name="testDelete">
<delete dir="test"/>
</target>
<!-- 运行前:没有则新建test目录,里面新建一个test.txt -->
<target name="testZip">
<zip destfile="test.zip">
<fileset dir="test">
<include name = "test.txt"/>
</fileset>
</zip>
</target>
<!-- 运行前:没有则新建test目录,然后在test目录新建一个txt文档 -->
<target name="testCopy">
<copy todir="testCopy" overwrite="true">
<fileset dir="test">
<include name="*.txt"></include>
</fileset>
</copy>
</target>
</project>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
一个 target 里可以有很多复制的插件,例如
<copy todir="${TEMP_APP_LIB}" overwrite="true">
<fileset dir="${COMMON_LIB_DIR}/EMP">
<include name="*.jar" />
</fileset>
<fileset dir="${COMMON_LIB_DIR}/Other">
<include name="*.jar" />
<exclude name="ebankpwd.jar"/>
</fileset>
<fileset dir="${COMMON_LIB_DIR}/idtrust">
<include name="*.jar" />
</fileset>
<fileset dir="${COMMON_LIB_DIR}/PowerEnter">
<include name="*.jar" />
</fileset>
</copy>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 自定义任务
Apache Ant 允许用户编写自己的任务。编写自己的任务非常容易。 下面给出了一些必要的步骤。请参考以下几个步骤。
- 首先创建一个 Java 类并扩展
org.apache.tools.ant.Task
类。 - 为每个属性创建
setter
和getter
方法。 - 如果
task
包含其他任务作为嵌套元素,则class
必须实现org.apache.tools.ant.TaskContainer
接口。 - 如果任务支持字符数据,请编写
public void addText(String)
方法。 - 对于每个嵌套元素,
write
,add
或addConfigured
方法。 - 编写一个
public void execute()
方法(不带参数)并抛出BuildException
。
一般内置的 task 就够用了,这里笔者不展开使用
# 关于帮助文档
授之以鱼不如授之以渔,笔者之前是直接列出来某个 task 怎么用的,但笔者不可能把每个都讲一遍,因为已经有人这么做了:官方文档里都写了。
我们可以打开 Ant 安装目录下的这个文件:apache-ant-1.10.12\manual\index.html
左侧就是目录,可以点进 Ant Tasks 看具体的
例如 Copy 这个 Task,右侧就是 Cppy 能用的属性,下面还有具体的用法。
# 用 Ant 编译 Java 程序
我们来做些实际上有用的事情。例如编译一个 Java 类。
我们新建一个目录 5-AntJava,里面新建一个 Hello.java 文件,内容如下:
public class Hello{
public static void main(String []args){
System.out.println("Hello Ant");
}
}
2
3
4
5
新建一个 build.xml,里面先编译,再运行 Java 类。
<?xml version="1.0" encoding="UTF8"?>
<project>
<property name="destEncoding" value="UTF-8" />
<target name = "compile">
<javac encoding="${destEncoding}" destdir=".">
<src path="."/>
</javac>
</target>
<target name = "run">
<java classname="Hello">
<classpath>
<pathelement location="."></pathelement>
</classpath>
</java>
</target>
<target name="clean">
<delete file="Hello.class"/>
</target>
</project>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
javac 任务也可以写成:
<javac includeantruntime="false" srcdir="./src" destdir = "test"></javac>
运行编译:可以看到有个 class 文件
D:\Projects\AntLearn\5-AntJava> ant compile
Buildfile: D:\Projects\AntLearn\5-AntJava\build.xml
compile:
BUILD SUCCESSFUL
Total time: 0 seconds
2
3
4
5
6
7
我们来试着运行:
D:\Projects\AntLearn\5-AntJava> ant run
Buildfile: D:\Projects\AntLearn\5-AntJava\build.xml
run:
[java] Hello Ant
BUILD SUCCESSFUL
Total time: 0 seconds
2
3
4
5
6
7
8
可以看到 Java 类被执行了
运行 clean:可以看到 class 文件被删除了
D:\Projects\AntLearn\5-AntJava> ant clean
Buildfile: D:\Projects\AntLearn\5-AntJava\build.xml
clean:
[delete] Deleting: D:\Projects\AntLearn\5-AntJava\Hello.class
BUILD SUCCESSFUL
Total time: 0 seconds
2
3
4
5
6
7
8
# 小结
本文介绍的内容:
- 构建脚本的 task
- 用 Ant 输出 HelloWorld
- Ant 的属性
- Ant 的文件
- 内置的 Task
- 怎么看帮助文档
- 用 Ant 运行 Java 程序
通过本文,作者应该能编写一些简单的程序了。大型的项目,也可以通过这些一个个简单的 task 来完成构建。