Ant的datatype和特性介绍(转载)

Ant的核心功能有两个基本概念:特性和datatypes。
1. Datatype概述:
Ant能够构建Java工程的主要问题域,这使得Ant成为用于构建和打包Java应用程序的强大工具。在构建一个典型Java工程时,多数步骤都用于处理文件和路径,例如classpath。Ant提供Datatypes来处理这两个概念。Ant的Datatype可以认为是类似于Java自身内建的类:data,它可以分发并提供任务。文件集和路径以及其他几种类型的datatype,构成了Ant构建文件的基本结构。
2. 特性概述:
Ant的特性控制机制通过参数化任何基于字符串的项目来实现构建文件的可扩展性和重用性。通过使用这些技术,用户对构建文件的控制能力显著增强了,例如,或许出于测试的目的,需要修改构建以使用不同版本的第三方库,这显得非常琐碎:
Ant –Dstruts.jar=/home/ant/newstruts/struts.jar
在这里,struts.jar表现为一个Ant特性,在构建文件中,以特殊的语法来引用它:${struts.jar}。
Ant的一个关键特性是它的不可变性;它一旦被设置就不能发生变化,此特性保持其初始值不变所带来的结果是,构建文件可以被设计成以指定顺序载入特性文件来使得user-、project-、environment-的控制重载。
3. 通过介绍DATATYPE和特性
在构建过程中对JAVA源代码的编译是一项基本的任务。Ant通过任务提供JAVA编译。该任务通过封装很多不同的JAVA编译器以及在通用任务定义之后与它们关联的开关,以一个通用的界面隐藏那些类的实现细节。该任务是一个通用的界面,它基于JDK 1.1及其后续版本、Jikes和其他几种JAVA编译器。
选项名称 JDK’s javac 开关选项 Ant’s 语法
Specify where to find input source files -sourcepath
Override location of bootstrap class files -bootclasspath
Override location of installed extensions -extdirs
Specify where to place generated class files -d destdir="build"
Specify character encoding used by source files -encoding encoding="…"
Generate class files for specific VM version -target 1.1 target="1.1"
Enable JDK 1.4 assertions -source 1.4 source="1.4"

JAVA编译过程并不仅仅指定源代码路径和目标路径,下表展示了Sun的JDK的javac命令行编译器开关和Ant的任务的对比:
(上表仅仅列出了一些选项)
Ant本身并不是一个JAVA编译器,而只是在诸如Sun的javac之类的编译器上做了一个包装,你还是需要一个JAVA编译器。在上表中介绍了几种新的属性(attribute)以及的几个新的子元素。大部分属性实际上使用的是布尔值—debug,optimize,nowarn,verbose和deprecation等。Ant在布尔值的表达上非常灵活,on,true,yes都被认为表示true,而其他的所有值都被认为是false。以及等元素展示了Ant最强的功能之一—路径和文件处理功能。每个元素都与路径有关。
下面比较一下Sun的JDK JAVA编译器和Ant的任务之间的差别:
Sun Java Compiler:
javac -d build\classes
-classpath lib\lucene-1.2-rc3\lucene-1.2-rc3.jar;
lib\jtidy-04aug2000r7-dev\build\Tidy.jar;
C:\AntBook\jakarta-ant-1.5\lib\ant.jar;
-sourcepath src
-g
src\org\example\antbook\ant\lucene\*.java
Ant task:
debug="${build.debug}"
includeAntRuntime="yes"
srcdir="${src.dir}">



在这个构建文件中,我们定义了路径compile.classpath:





“${…}”符号表示一个Ant特性,作用是将名字直接影射成字符串值。
子元素使用引用(reference)来指定路径(预先定义的路径)。预先定义的指示了要使用的JAR文件,在这里是使用location属性的特性指定的。
Srcdir属性隐式定义了包含指定目录数下所有文件的文件集,嵌套的指定了将文件限定为JAVA源文件的模式集。
4. 路径
路径就是经过排序的路径元素列表。它类似于JAVA CLASSPATH,列表中的元素可以是一个由分隔符隔开的文件或者目录,一个路径的定义如下:



location属性允许你指定单个的文件或者目录。也可以通过另一个路径来扩展当前路径,使用path代替location。



路径定义中元素间的分隔符可以是分号(;)也可以是逗号(:),路径的分隔即可以使用正斜杠,也可以使用反斜杠,无需考虑操作系统的差异,这使得它容易跨平台。如果路径结构中只有一个目录或位置,则可以使用快捷的表达方式如
或者
路径也可以是一个文件集合:





需要注意的是Ant不保证里的内容是有序的。在路径里的每个元素是从头到尾排序的,这使得所有在文件集里的文件可以集中在一个路径下,然而,其在文件集里的顺序是不确定的。
5. 文件集
所有的构建过程都会隐式的对一系列文件进行操作,无论是编译,复制,删除还是任何其他方式的操作。Ant将文件集看成是本地的datatype。难以想象会有任何实用的构建不会使用到文件集。一些任务支持路径,而路径隐含厘支持文件集,而其他任何一些任务则直接支持文件集。
文件集指的是同一目录下的一系列文件。默认情况下,一个只指定了一个根目录的文件集包含该目录下整个目录数中的所有文件,包含所有递归的子目录下的文件。拷贝例子:



在当前状态下,所有web目录中的文件从web目录被复制到new_web目录下,这个例子可以进化成只复制指定的文件、在复制期间通过令牌替换对文件进行替换,以及对new_web目录进行目录层次扁平化。
例子二:在一些构建过程中,经常需要在构建文件集时包含(include)一些文件或者排除(exclude)一些文件。下面是一些典型的例子:
包含所有在lib目录下的JAR文件(不考虑递归和子目录):



包含所有在test目录下以单词”Test”结尾的.java文件:



Web目录下所有非JSP页面的文件:



默认情况下,include和exclude中的值的大小写是民该的,但是可以通过设置casesensitve=”false”来取消它。元素被称为模式集。
6. 模式集
文件集利用Ant的另外一个核心datatype:模式集,来实现包含/排除能力。模式集是与模式相匹配的文件的汇总。模式集本身并不指向任何实际的文件,除非它被嵌套入文件集,那样它就会以指定的目录为根。模式集是一种路径匹配指定,类似于基于Unix和MS-DOS的文件匹配。*.jar用语表示所有在第一层目录下的所有扩展名为.jar的文件。**/*.jsp表示在整个目录数中所有扩展名为.jsp的文件。模式匹配的功能如下:
*指代从零到任意长度的字符。
?指代单一的字符。
**作为目录名,代表目录数上从当前节点往下的所有目录,可以是零到任意多个目录。
以/或\结尾的模式意味着结尾是**。
暗含有模式集,但是考虑到需要在多个文件集中重用,模式集也可以单独指定,下表列出了元素的可用属性。
includes:应包含的文件模式列表,以逗号分隔,省略时包含所有文件。
excludes:应排除的文件模式列表,以逗号分隔,省略时表示不排除任何文件(除认为默认的排除文件)。
includesfile:文件名称;该文件的每一行被看作是包含模式。如果要指定多个要包含的文件,可以通过嵌套includesfile元素来实现。
excludesfile: 文件名称;该文件的每一行被看作是排除模式。如果要指定多个要排除的文件,可以通过嵌套excludesfile元素来实现。

Excludes具有有限权,如果一个文件既与include模式匹配,又与exclude模式匹配,则将被排除。符合这些属性的元素可以成为元素的子元素以增加它的灵活性和可控性。这些元素是:
,,,。这些元素都有个name属性,对于,他们的name属性分别指的是included和excluded模式。对于,它们的name属性特性分别表示各自的文件名称。每种元素都有if/unless属性。这些是有条件的模式集。
例子:
在文件集中使用元素时总是显示指定。



文件集默认包含有模式集。



这等同于:





我们仅仅定义了*.jsp,只有在web目录下的JSP文件被复制,而其子目录中的文件则都不会被复制。模式集可以被另外一个模式集嵌套,例如:






嵌套的模式集并不是必须的。
7. 选择器:
Ant1.5包含了一个精密的新特性,名为选择器(selector),它用来选择包含在文件集中的文件。
Ant内建的选择器及其说明:
:基于模式匹配文件,工作方式类似于模式集的元素。
:基于目录深度范围来选择文件。
:以小于、等于、大于该指定值为条件来选择文件。
:以最后修改时间早于、迟于或者等于指定值来选择文件
:选择存在于其他目录数的文件
:选择比其他目录下相对应的文件更新的文件
:选择包含指定字符串的文件.
这些选择器都可以被合并到选择器容器内以提供分组和逻辑表达。这些容器就是。容器可以嵌套,用以表达负责的逻辑选择结构。
例子:结合使用








任务复制所有只存在于web目录而不存在于currentfiles目录的文件。使用选择器,我们可以选择只包含特定字符串的文件:






只有在web目录下,且文件中包含文本”System”文件才被复制到currentfiles目录。默认情况下对大小写敏感,可以通过casesensitive=”no”来进行修改。

DATATYPE元素明明
Ant在其API工公开了模式集、文件集和路径以及一些其他的datatype。框架并不强制要求给这些datatype元素命名,任务可以无需显示指定就可以支持这些datatype。
任务就是一个隐含包含文件集的例子。它通过:
includes,excludes,includesfile,excludesfile属性以及:
,,,元素来实现。请注意有一个强制属性dir属性,但是是通过srcdir属性来指定的,这样做的目的是区分源目录和目标目录。
任务也可以用来例示允许将路径做为嵌套元素的任务,可以指定不同类型的路径();并且还可以通过任意方式结合。例如可以使用两个标记来编译两个目录数下的源代码到一个输出目录:





8. 过滤集FilterSet
在构建过程中,基于动态构建信息或状态对文件进行简单文本替换的情况是很常见的,两个最主要支持过滤集功能的任务是。在下列两种情况下使用带有过滤的复制会带来便利:
将构建与包含当前日期或版本信息的文件相绑定,例如编制文档。
对配制文件进行有选择的注释。
在将源文件拷贝或者移动到目录文件时将进行一个过滤操作来替换源文件中带标记的文本。对于 经过过滤的拷贝操作,源文件不被改变。标记用两端被标记分隔符隔开的文本进行定义。默认的分隔符是”@”,但是可以使用里的begintoken和endtoken属性进行修改。
例子:在构建文件时在文件中插入时间戳
将生成文件中日期和时间戳替换为构建实际运行的日期和时间,而保持原文件不变:

Ant Book

System build time: @DATE@ @ @TIME@



这里的@DATA@和@TIME@在复制过程中将被替换:









任务创建了Ant的DSTAMP和TSTAMP特性。${DSTAMP}和${TSTAMP}的值分别是日期和时间戳。任务句有依赖性检查,因此它不会对修改时间戳早于目标文件的源文件进行复制。因为经过过滤的copy操作总会替换目标文件,因此我们设置overwrite=”true”来关闭依赖性检查,在对于JSP文件的应用经过过滤的copy操作结果如下:

Ant Book

System build time: 20020207 @ 1501


注意:不要读二进制文件进行过滤操作。

9. 过滤链和过滤阅读器
过滤阅读器是一个简单的过滤器,它输入文件,并在输出之前对其文字进行移除和修改。过滤链是一组经过排序的一个或者多个过滤阅读器。Ant内置一些过滤阅读器:
:为在类文件中发现的基本的和字符串datatype常量生成”name=value”行
:替换Ant特性值
:取出指定数量的前几行
:只允许包含指定字符串的行通过
:只允许符合正则表达式的行通过
:所有行都有预先定义的前缀
:如同过滤集那样,执行标记替换
:移除JAVA风格的注释
:移除换行符,默认为”\r”和”\n”,但是要移除的字符也可以指定
:移除以指定的字符集合开头的行
:将tab符号替换为指定数量的空格
:取出指定数量的最后几行
有四个任务支持过滤链:。将注释从JAVA特性文件中剥离,或者去掉注视装载而将注释留在开发者文件里,是中使用过滤阅读器的一个直接原因。
属性文件为:
#
config.parameter=47

将其复制到build目录下:








则相应的文件build/confi.properties将不会再有注释行,而只有内容:
config.parameter=47.
还可以通过使用任务可以从java代码中取出数值作为参数传入Ant。为定义常量取得一个接口:
package org.example.antbook;
public interface Constants {
public static final String VERSION ="1.7";
}
将代码编译到build目录下。在任务中使用过滤阅读器,就可以给予Ant获取VERSION常量的途径:






Constants.VERSION = ${Constants.VERSION}
输出结果如下:Constants.VERSION = 1.7
注意:直接操作于.class文件,而不是.java文件。

10. 映射器Mapper
Ant的mapper datatype用于将一批文件与另外的文件进行匹配。下表中列出了几种Ant内置的映射器,映射器由以及其他几种任务调用。视映射器类型而定,from和to属性可能是必需的。

映射器类型。映射器用于任务,可以减少目录的层次,也可以根据文档的修改日期检查全部文件并映射到一个文档中

identity:目标文件和源文件名称相同
flatten:目标文件和源文件名称相同,且目标文件名中去除所有目录路径
merge:全部源文件映射到以to属性指定的单一目标文件。
glob:在from模式中用一个星号指代的部分由to模式中的内容替代,只对匹配from模式的文件进行操作。
package:Glob映射器的子类,它与glob功能类似,但与glob不同的是它会将目录分隔符替换为点字符,这样可以将一个具有目录层次结构的包目录的文件映射成扁平目录结构,并且可以通过文件名保留其包结构。
regexp:from和to模式都定义为正则表达式,只对匹配from表达式的文件进行操作。

Identity映射器:目标文件和源文件名称相同,to和from属性在该映射器里都不起作用:任务使用与不使用该映射器是一样的,默认就已经使用该映射器。

Flatten映射器:要将所有JSP页面从web目录结构复制到一个单一扁平的目录下时,应该以下列方式使用flatten映射器:





注意:如果有多个文件拥有相同的文件名,不考虑到目录,将只有一个文件被复制到该目录,并且不能确定是哪一个。

Merge映射器:目标文件名由to属性指定,全部源文件映射到这个单一的目标文件:

当很多文件映射到一个目标文件时,merge影射器与任务同时使用。例如,很多文件被打包成单一的ZIP文件,如果该ZIP文件包括所有日期最新的源文件,则应该设置一个特性:





Glob映射器:同时使用to和from属性,两个属性都可以使用星号模式。匹配from属性规定模式的文字被替换成to模式。

如下冽所示,glob映射将对于将文件复制到新文件名的方式制作备份文件非常有用。不能匹配from模式的文件将被忽略。




全部JSP文件从web目录被拷贝到new_web目录中,并保留了目录层次结构,但是所有的源.jsp在new_web目录下都被改名成了.jsp.bak。

Package映射器:是Glob映射器的一种特殊形式,它将与from模式匹配的片段转换成to模式规定的以”.”分隔的包字符串。转换过程简单的将目录分隔符斜杠或者反斜杠变成点。其结果是一个扁平的目录结构,其中包含了设想中的Java文件,这些java文件需要与嵌入在文件名中的完全合格的类名称的数据文件相匹配。更准确的说,该映射器主要用于由任务生成的数据。

在运行测试用例中,生成的数据文件被写到一个单一的目录下,并命名为TEST-<完全限定的类名>.xml。为了证实该测试用例的数据文件不早于其相应的JAVA文件,我们在任务中加入package映射器:



from="*.java" to="${results.dir}/TEST-*.xml" />

11. 特性Property
特性由于其名称和值的关系,可以粗略的看成是变量。
Ant内建特性:
ant.file:构建文件的绝对路径
ant.home:用于Ant执行的根路径
ant.java.version:Ant检测到的JVM的版本
ant.project.name:当前执行的工程的名称;可由中的name属性设置
ant.version:Ant版本号
basedir:工程基目录的绝对路径,由中的basedir特性设置

Ant特性通常依赖于其使用时的上下文环境,由构建文件中的${property.name}来表示。要检查上述特性,可以使用任务:







所有JAVA虚拟机系统的特性都会隐式的成为ANT特性,并允许对一些重要信息诸如用户的主目录以及当前的用户名称都可以按需要进行修改。JVM的特性在不同的平台上是不同的,但他们中有很多是值得你信任的。

1. 通过任务设置特性
该任务允许在构建文件中自定义特性,最常用的特性是以下几种:
Name/Value对
从特性文件中载入特性集合
载入环境变量

可以使用


在工程的根目录创建一个名为build.properties的文件,这也是构建文件所在的目录。文件包含以下内容:
build.debug=off
使用任务中的一个变量:

特性文件中的特性值也可以是对特性的引用,例如
build.dir=build
output.dir=${build.dir}/output

注意:引用相对路径的特性最好使用location变量来设置。
因为特性是不可以改变的,因此通过文件载入特性时可以给出它们的名称前增加前缀。例如,可以使用前缀prefix=”temp”,这样创建好的特性将变为temp.build.dir和temp.output.dir。当我们需要同时从两个特性文件中载入同名特性时不至于引起歧义。

特性测试:





特性值一旦设置,就不能修改,所以结果为
[echo] debugging is turned off.

另一个重要的变量允许将环境变量作为特性。为了避免环境变量与已有的Ant特性冲突,环境变量在载入时被加上前缀,例如

所有的环境变量被载入为Ant的内部特性时都被加上env.前缀。

特性的一个关键用途是抽象化系统文件系统路径,它使得任务只需处理特性名即可,而具体值的确立则在别处定义或者生成(多数情况下)。不使用绝对路径定义构建也很容易。只需将路径定义为项目的基路径下的相对路径。
任务还有另一个变量可以将指定路径设置为绝对路径:

build.dir特性的值并不简单的赋为字符串build,当前工程的基路径(通常是build.xml所在的路径)会被用作相关引用的根目录,而完整的路径将被解析为/home/erik/AntBook/Sections/Learning/datatypes/build。建议使用location功能将逻辑的相对路径锁定到绝对路径,并在对文件和目录操作时使用直接引用。
2. 任务怎样区别与其他的任务?
任务的特殊之处在于它具有特殊的权限,可以在之外执行:它可以独立的成为的直接子元素。所有位于target之外的任务都将在target运行之前被计算,因此,建议将所有这些中的”非target声明”放在target声明之前,以避免混乱。
3. 检查资源的可用性:
当指定资源存在时,任务会设置特性值,它能够检查以下内容:
classpath下的某个类是否存在
某个文件或者目录是否存在
某个JVM系统资源是否存在
检查classpath下某个类是否存在:
classname="xdoclet.doc.DocumentDocletTask"
classpath="${xdoclet.jar}"/>

如果类xdoclet.doc.DocumentDocletTask被发现,xdoclet.present就设为true.否则,就没有值。所以结果是xdoclet.present=true或者
xdoclet.present=${xdoclet.present}
(一个未定义的属性不能被解析,直接按照字面意思来使用)
检查某个文件或者目录是否存在:
如果存在,则设置特性值。
file="${lib.dir}/lib.properties"
type="file"/>
检查JVM系统资源是否存在:
最后一项有效性检查是资源,即在classpath下可查找的任意文件。通常用语检查配制文件的有效性:
resource=”org/example/etc/struts.xml” />

4. 忽略不必要的步骤:以节省时间
该任务以确认目标文件与源文件相比是否是最新的。多数任务都会在内部自动检查( etc.)。但是有一些需要你自己去实施检查,例如Junit的一些任务。


from="*.java" to="${build.dir}/classes/*.class" />

在本例中,如果源目录数中的每个模块都不新于对应的.class文件,则特性tests.unnecessary的值就设为true。
5. 用测试条件
通过逻辑运算符来提供特性设置的威力。
:Exactly the same semantics and syntax as the task, except property and value are ignored. Evaluates to true if the resource is available.
:xactly the same semantics and syntax as the task, except property and value are ignored. Evaluates to true if file(s) are up-to-date.
:Evaluates to true if the O/S family (mac, windows, dos, netware, os/2, or unix), name, architecture, and version match.
:Evaluates to true if both properties have the same value.
:Evaluates to true if the property exists.
:Uses the same syntax as the task, evaluating to true if the checksum of the file(s) match.
:Checks for a status code < 500 from a URL.
:Checks for a socket listener on a specified port and host.
:Byte-for-byte file comparison between two files.
:Tests whether one string contains another, optionally case-sensitive.
:True if the value is on, true, or yes.
:The negation of .
例子:




to="${build.dir}/classes/*.class" />



to="${test.dir}/*.class" />







如果与测试有关的文件都是最新的,则tests.unnecessary被设置为true。
6. 在命令行中设置特性
通过命令行的-D和-propertyfile选项可以设置特性或者从特性文件中载入特性。
7. 用创建构建的时间戳

基于当前日期/时间自动设置三个特性
DSTAMP:”yyyymmdd”
TSTAMP:”hhmm”
TODAY:”month day year”

可以使用嵌套元素来指定特定规范的时间戳,例如

pattern="yyyy-MM-dd'T'HH:mm:ss" />


还可以为时间戳特性增加前缀:

以上代码设置了三个特性start.DSTAMP,start.TSTAMP,start.TODAY。

8. 从xml文件中载入特性
下面例子被设计成可以为不同的客户提供个性化的操作,每个客户响应的都有一个特性信息的XML文件,诸如名字或者其他一些特定运行细节:
读取XML文件,照里面的元素和特性的原样创建特性。
构建文件可以很容易的使用这些信息:






classname = ${customer.settings.impl}



在开始部分,我们使用customer特性定义客户的昵称,其默认值为acme,构建在verbose模式的输出结果为:
main:
[echo] Building for Acme, Inc....
[echo] classname = org.example.antbook.acme.SomeClass
这间接允许我们在构建时使用任意的客户名来重载customer的值,例如:
ant –Dcustomer=joes_garage
具有属性prefix决定特性的前缀,validate=”true”时进行有效性检查,默认不检查!

你可能感兴趣的:(Ant,设计模式,正则表达式,JSP,lucene)