Ant之build.xml詳解---可用
阿新 • • 發佈:2019-01-07
Ant的概念 :在Eclipse中使用Ant Ant是Java平臺下非常棒的批處理命令執行程式,能非常方便地自動完成編譯,測試,打包,部署等等一系列任務,大大提高開發效率。
Ant和make命令很像。當編譯Linux核心及一些軟體的源程式時,經常要用這個命令。Make命令其實就是一個專案管理工具,而Ant所實現功能與此類似。像make,gnumake和nmake這些編譯工具都有一定的缺陷,但是Ant卻克服了這些工具的缺陷。
Ant執行需要的XML格式的檔案不是Shell命令檔案,它是由一個Project組成的,而一個Project又可分成可多target,target再細分又分成很多task,每一個task都是通過一個實現特定介面的java類來完成的。
Ant是由一個內建任務和可選任務組成的。Ant執行時需要一個XML檔案(構建檔案)。Ant通過呼叫target樹,就可以執行各種task。每個task實現了特定介面物件。由於Ant構建檔案時XML格式的檔案,所以和容易維護和書寫,而且結構很清晰。
Ant 開發---Ant的構建檔案
當開始一個新的專案時,首先應該編寫Ant構建檔案。構建檔案定義了構建過程,並被團隊開發中每個人使用。Ant構建檔案預設命名為build.xml,也可以取其他的名字。只不過在執行的時候把這個命名當作引數傳給Ant。構建檔案可以放在任何的位置。一般做法是放在專案頂層目錄中,這樣可以保持專案的簡潔和清晰。下面是一個典型的專案層次結構:
(1) src存放檔案。
(2) class存放編譯後的檔案。
(3) lib存放第三方JAR包。
(4) dist存放打包,釋出以後的程式碼。
Ant構建檔案是XML檔案。每個構建檔案定義一個唯一的專案(Project元素)。每個專案下可以定義很多目標(target元素),這些目標之間可以有依賴關係。當執行這類目標時,需要執行他們所依賴的目標。 每個目標中可以定義多個任務,目標中還定義了所要執行的任務序列。Ant在構建目標時必須呼叫所定義的任務。任務定義了Ant實際執行的命令。Ant中的任務可以為3類:
(1) 核心任務。核心任務是Ant自帶的任務。
(2) 可選任務。可選任務實來自第三方的任務,因此需要一個附加的JAR檔案。
(3) 使用者自定義的任務。使用者自定義的任務實使用者自己開發的任務。
1.<project>標籤
每個構建檔案對應一個專案。<project>標籤時構建檔案的根標籤。它可以有多個內在屬性,就如程式碼中所示,其各個屬性的含義分別如下。
(1) default表示預設的執行目標,這個屬性是必須的。
(2) basedir表示專案的基準目錄。
(3) name表示專案名。
(4) description表示專案的描述。
每個構建檔案都對應於一個專案,但是大型專案經常包含大量的子專案,每一個子專案都可以有自己的構建檔案。
2.<target>標籤
一個專案標籤下可以有一個或多個target標籤。一個target標籤可以依賴其他的target標籤。例如,有一個target用於編譯程式,另一個target用於聲稱可執行檔案。在生成可執行檔案之前必須先編譯該檔案,因策可執行檔案的target依賴於編譯程式的target。Target的所有屬性如下。
(1).name表示標明,這個屬性是必須的。
(2).depends表示依賴的目標。
(3)if表示僅當屬性設定時才執行。
(4)unless表示當屬性沒有設定時才執行。
(5)description表示專案的描述。
Ant的depends屬性指定了target的執行順序。Ant會依照depends屬性中target出現順序依次執行每個target。在執行之前,首先需要執行它所依賴的target。程式中的名為run的target的depends屬性compile,而名為compile的target的depends屬性是prepare,所以這幾個target執行的順序是prepare->compile->run。 一個target只能被執行一次,即使有多個target依賴於它。如果沒有if或unless屬性,target總會被執行。
3.<mkdir>標籤
該標籤用於建立一個目錄,它有一個屬性dir用來指定所建立的目錄名,其程式碼如下:
<mkdir dir=”${class.root}”/>
通過以上程式碼就建立了一個目錄,這個目錄已經被前面的property標籤所指定。
4<jar>標籤
該標籤用來生成一個JAR檔案,其屬性如下。
(1) destfile表示JAR檔名。
(2) basedir表示被歸檔的檔名。
(3) includes表示別歸檔的檔案模式。
(4) exchudes表示被排除的檔案模式。
5.<javac標籤>
該標籤用於編譯一個或一組java檔案,其屬性如下。
(1).srcdir表示源程式的目錄。
(2).destdir表示class檔案的輸出目錄。
(3).include表示被編譯的檔案的模式。
(4).excludes表示被排除的檔案的模式。
(5).classpath表示所使用的類路徑。
(6).debug表示包含的除錯資訊。
(7).optimize表示是否使用優化。
(8).verbose 表示提供詳細的輸出資訊。
(9).fileonerror表示當碰到錯誤就自動停止。
6.<java>標籤
該標籤用來執行編譯生成的.class檔案,其屬性如下。
(1).classname 表示將執行的類名。
(2).jar表示包含該類的JAR檔名。
(3).classpath所表示用到的類路徑。
(4).fork表示在一個新的虛擬機器中執行該類。
(5).failonerror表示當出現錯誤時自動停止。
(6).output 表示輸出檔案。
(7).append表示追加或者覆蓋預設檔案。
7.<delete>標籤
該標籤用於刪除一個檔案或一組檔案,去屬性如下。
(1)/file表示要刪除的檔案。
(2).dir表示要刪除的目錄。
(3).includeEmptyDirs 表示指定是否要刪除空目錄,預設值是刪除。
(4).failonerror 表示指定當碰到錯誤是否停止,預設值是自動停止。
(5).verbose表示指定是否列出所刪除的檔案,預設值為不列出。
8.<copy>標籤
該標籤用於檔案或檔案集的拷貝,其屬性如下。
(1).file 表示原始檔。
(2).tofile 表示目標檔案。
(3).todir 表示目標目錄。
(4).overwrite 表示指定是否覆蓋目標檔案,預設值是不覆蓋。
(5).includeEmptyDirs 表示制定是否拷貝空目錄,預設值為拷貝。
(6).failonerror 表示指定如目標沒有發現是否自動停止,預設值是停止。
(7).verbose 表示制定是否顯示詳細資訊,預設值不顯示。
Ant的資料型別
在構建檔案中為了標識檔案或檔案組,經常需要使用資料型別。資料型別包含在org.apache.tool.ant.types包中。下面鏡簡單介紹構建檔案中一些常用的資料型別。
1. argument 型別
由Ant構建檔案呼叫的程式,可以通過<arg>元素向其傳遞命令列引數,如apply,exec和java任務均可接受巢狀<arg>元素,可以為各自的過程呼叫指定引數。以下是<arg>的所有屬性。
(1).values 是一個命令引數。如果引數種有空格,但又想將它作為單獨一個值,則使用此屬性。
(2).file表示一個引數的檔名。在構建檔案中,此檔名相對於當前的工作目錄。
(3).line表示用空格分隔的多個引數列表。
(4).path表示路徑。
2.ervironment 型別
由Ant構建檔案呼叫的外部命令或程式,<env>元素制定了哪些環境變數要傳遞給正在執行的系統命令,<env>元素可以接受以下屬性。
(1).file表示環境變數值得檔名。此檔名要被轉換位一個絕對路徑。
(2).path表示環境變數的路徑。Ant會將它轉換為一個本地約定。
(3).value 表示環境變數的一個直接變數。
(4).key 表示環境變數名。
注意 file path 或 value只能取一個。
3.filelist型別
Filelist 是一個支援命名的檔案列表的資料型別,包含在一個filelist型別中的檔案不一定是存在的檔案。以下是其所有的屬性。
(1).dir是用於計算絕對檔名的目錄。
(2).files 是用逗號分隔的檔名列表。
(3).refid 是對某處定義的一個<filelist>的引用。
注意 dir 和 files 都是必要的,除非指定了refid(這種情況下,dir和files都不允許使用)。
4.fileset型別
Fileset 資料型別定義了一組檔案,並通常表示為<fileset>元素。不過,許多ant任務構建成了隱式的fileset,這說明他們支援所有的fileset屬性和巢狀元素。以下為fileset 的屬性列表。
(1).dir表示fileset 的基目錄。
(2).casesensitive的值如果為false,那麼匹配檔名時,fileset不是區分大小寫的,其預設值為true.
(3).defaultexcludes 用來確定是否使用預設的排除模式,預設為true。
(4).excludes 是用逗號分隔的需要派出的檔案模式列表。
(5).excludesfile 表示每行包含一個排除模式的檔案的檔名。
(6).includes 是用逗號分隔的,需要包含的檔案模式列表。
(7).includesfile 表示每行包括一個包含模式的檔名。
5.patternset 型別
Fileset 是對檔案的分組,而patternset是對模式的分組,他們是緊密相關的概念。
<patternset>支援4個屬性:includes excludex includexfile 和 excludesfile,與fileset相同。Patternset 還允許以下巢狀元素:include,exclude,includefile 和 excludesfile.
6.filterset 型別
Filterset定義了一組過濾器,這些過濾器將在檔案移動或複製時完成檔案的文字替換。
主要屬性如下:
(1).begintoken 表示巢狀過濾器所搜尋的記號,這是標識其開始的字串。
(2).endtoken表示巢狀過濾器所搜尋的記號這是標識其結束的字串。
(3).id是過濾器的唯一標誌符。
(4).refid是對構建檔案中某處定義一個過濾器的引用。
7.Path型別
Path元素用來表示一個類路徑,不過它還可以用於表示其他的路徑。在用作揖個屬性時,路經中的各項用分號或冒號隔開。在構建的時候,此分隔符將代替當前平臺中所有的路徑分隔符,其擁有的屬性如下。
(1).location 表示一個檔案或目錄。Ant在內部將此擴充套件為一個絕對路徑。
(2).refid 是對當前構建檔案中某處定義的一個path的引用。
(3).path表示一個檔案或路徑名列表。
8.mapper型別
Mapper型別定義了一組輸入檔案和一組輸出檔案間的關係,其屬性如下。
(1).classname 表示實現mapper類的類名。當內建mapper不滿足要求時,用於建立定製mapper.
(2).classpath表示查詢一個定製mapper時所用的型別路徑。
(3).classpathref是對某處定義的一個類路徑的引用。
(4).from屬性的含義取決於所用的mapper.
(5).to屬性的含義取決於所用的mapper.
(6).type屬性的取值為identity,flatten glob merge regexp 其中之一,它定義了要是用的內建mapper的型別。
Ant 的執行
安裝好Ant並且配置好路徑之後,在命令列中切換到構建檔案的目錄,輸入Ant命令就可以執行Ant.若沒有指定任何引數,Ant會在當前目錄下查詢build.xml檔案。如果找到了就用該檔案作為構建檔案。如果使用了 –find 選項,Ant 就會在上級目錄中找構建檔案,直至到達檔案系統得跟目錄。如果構建檔案的名字不是build.xml ,則Ant執行的時候就可以使用 –buildfile file,這裡file 指定了要使用的構建檔案的名稱,示例如下:
Ant如下說明了表示當前目錄的構建檔案為build.xml 執行 ant 執行預設的目標。
Ant –buildfile test.xml
使用當前目錄下的test.xml 檔案執行Ant ,執行預設的目標
ant的build.xml檔案例項分析
以build_for_ejb_templet.xml為示例,講解Ant中常用的元素和任務。
約定: "…"表示這裡有很多程式碼,未列出
build_for_ejb_templet.xml任務的分為以下幾大部分
i. 開始
ii. 初始化
iii. 定義classpath
iv. 為編譯作準備
v. 編譯EJB部分
vi. 編譯WEB部分
vii. 編譯J2EE Application
viii. 部署Application
ix. 建立元件的API
x. 確定build的目標
build_for_ejb_templet.xml的講解
開始
<?xml version="1.0" encoding="UTF-8"?>
講解:encoding="UTF-8"表示XML檔案採用UTF-8編碼格式,如果要使用GBK編碼,需定義為encodeing="GBK"。
<!--
Build file for 'componentName'
Creation date : $Date: yyyy-m-d $
Updated date : $Date: yyyy-m-d $
Author: developerName
Copyright 2002 CompanyName, Inc. All rights reserved.
-->
講解:此部分為檔案內容的簡介,包括檔名稱、建立日期、最後修改日期、建立檔案的作者、版權。
componentName 表示 檔名稱
yyyy-m-dd 表示 建立日期、最後修改日期的格式,如2002-5-1
developerName 表示 建立檔案的作者
CompanyName 表示 公司名稱或URL
<project name="componentName" default="core" basedir=".">
…
</project>
講解:此部分定義了一個名稱為componentName的專案元素,預設的任務為"core"任務,根目錄為當前目錄。componentName表示元件的名稱,這裡指EJB的名稱。
初始化
<target name="init">
…
</target>
講解:此部分用於初始化所有的變數
<property file="../../build.properties" />
講解:匯入專案根目錄下build.properties中的全域性變數,開發人員也可以在此檔案中重新定義全域性變數。
<property name="jboss.lib" value="${jboss.home}/lib" />
<property name="jboss.client" value="${jboss.home}/client" />
<property name="jboss.deploy" value="${jboss.home}/server/${jboss.configuration}/deploy" />
…
<property name="jboss.dir" value="${jboss.home}" />
…
<property name="deploy.ormi" value=""/>
<property name="deploy.username" value=""/>
<property name="deploy.password" value=""/>
講解:定義和Jboss Application Server有關的變數,包括lib目錄、client目錄、
deploy目錄和J2EE Application部署要用到的一些變數。
<property name="name" value="componentName"/>
講解:定義元件的名稱
<property name="src.dir" value="${basedir}/src"/>
講解:定義原始碼目錄路徑
<property name="etc.dir" value="${basedir}/etc"/>
講解:定義資源目錄路徑
<property name="lib.dir" value="${basedir}/lib"/>
講解:定義庫目錄路徑
<property name="build.dir" value="${basedir}/build"/>
講解:定義build目錄路徑
<property name="src.main.dir" value="${src.dir}/main"/>
講解:定義原始碼的主目錄路徑
<property name="src.ejb.dir" value="${src.main.dir}/ejb"/>
講解:定義存放EJB的原始碼目錄路徑
<property name="src.javabean.dir" value="${src.main.dir}/javabean"/>
講解:定義存放JavaBean的原始碼目錄路徑
<property name="src.servlet.dir" value="${src.main.dir}/servlet"/>
講解:定義存放Servlet的原始碼目錄路徑
<property name="src.web.dir" value="${src.main.dir}/web"/>
講解:定義存放WEB部分檔案(包括JSP程式、HTML檔案、圖片、CSS檔案、JS指令碼等)的目錄路徑
<property name="javadoc.dir" value="${lib.dir}/docs/api"/>
講解:定義存放元件API的開發檔案目錄路徑
<property name="ejb-classes.dest" value="${lib.dir}/ejb"/>
講解:定義存放EJB的編譯程式碼目錄路徑
<property name="javabean-classes.dest" value="${lib.dir}/javabean"/>
講解:定義存放JavaBean的編譯程式碼目錄路徑
<property name="web-classes.dest" value="${lib.dir}/web/WEB-INF/classes" />
講解:定義WEB目錄的類目錄路徑
<property name="web-lib.dest" value="${lib.dir}/web/WEB-INF/lib" />
講解:定義WEB目錄的庫目錄名稱
<property name="pkg-dist.name" value="${name}-pkg"/>
講解:定義壓縮文件的名稱
<property name="ProjectName.components.home" value="../../components" />
講解:定義專案的元件目錄路徑
<!-- Define componentName Component -->
講解:這段為註釋,說明以下是定義當前元件的變數
<property name="ProjectName.componentName.name" value="componentName"/>
講解:定義當前元件的名稱
<property name="ProjectName.componentName.home" value="${ProjectName.components.home}/componentName"/>
講解:定義當前元件的目錄路徑
<property name="ProjectName.componentName.classbindir"
value="${ProjectName.componentName.home}/lib/ejb"/>
講解:定義當前元件的EJB編譯目錄路徑
<property name="ProjectName.componentName.ejbjar"
value="${ProjectName.componentName.home}/build/componentName-ejb.jar"/>
講解:定義當前元件內的EJB包的路徑
<property name="ProjectName.componentName.ejbjar.client"
value="${ProjectName.componentName.home}/build/componentName-ejb-client.jar"/>
講解:定義當前元件內的EJB客戶端包的路徑
<!-- Define referencesComponentName Component -->
講解:這段為註釋,說明以下是定義引入其它元件的變數
<property name="ProjectName.referencesComponentName.name"
value="referencesComponentName"/>
講解:定義指定元件的名稱
<property name="ProjectName.referencesComponentName.home"
value="${ProjectName.components.home}/referencesComponentName"/>
講解:定義指定元件的目錄路徑
<property name="ProjectName.referencesComponentName.classbindir"
value="${ProjectName.referencesComponentName.home}/lib/ejb"/>
講解:定義指定元件的EJB編譯目錄路徑
<property name="ProjectName.referencesComponentName.ejbjar"
value="${ProjectName.referencesComponentName.home}
/build/referencesComponentName-ejb.jar"/>
講解:定義指定元件內的EJB包的路徑
<property name="ProjectName.referencesComponentName.ejbjar.client"
value="${ProjectName.referencesComponentName.home}
/build/referencesComponentName-ejb-client.jar"/>
講解:定義指定元件內的EJB客戶端包的路徑
<property name="build.classpath"
value="${jboss.client}/jboss-j2ee.jar:${jboss.client}
/jnp-client.jar:${jboss.client}/jnp-client.jar:${jboss.client}
/jbossmq-client.jar:${jboss.client}/jbosssx-client.jar:${jboss.client}
/concurrent.jar:${jboss.client}/jaas.jar:${jboss.lib}
/jboss-jmx.jar:${jboss.home}/server/${jboss.configuration}
/lib/jbosssx.jar:${jboss.home}/server/${jboss.configuration}
/lib/mail.jar:${servlet-lib.path}:${ejb-classes.dest}:
${web-classes.dest}:${ProjectName.componentName.classbindir}:
${ProjectName.componentName.ejbjar.client}:
${ProjectName.referencesComponentName.classbindir}:
${ProjectName.referencesComponentName.ejbjar.client}" />
講解:定義classpath,編譯bean時要用到。這是定義classpath的一種方法,下面還有另一種方法。
定義classpath
<!-- ================================================================== -->
<!-- Define the classpath for compile the component -->
<!-- ================================================================== -->
<path id="base.path">
<pathelement location="${jboss.client}/jboss-j2ee.jar" />
<pathelement location="${jboss.client}/jnp-client.jar" />
<pathelement location="${jboss.client}/jbossmq-client.jar" />
<pathelement location="${jboss.client}/jbosssx-client.jar" />
<pathelement location="${jboss.client}/concurrent.jar" />
<pathelement location="${jboss.client}/jaas.jar" />
<pathelement location="${jboss.lib}/jboss-jmx.jar" />
<pathelement
location="${jboss.home}/server/${jboss.configuration}/lib/jbosssx.jar" />
<pathelement
location="${jboss.home}/server/${jboss.configuration}/lib/mail.jar" />
</path>
講解:此段定義應用伺服器中包檔案,如支援ejb的jboss-j2ee.jar、支援客戶端程式的jnp-client.jar、jbossmq-client.jar、jbosssx-client.jar、支援JavaMail的mail.jar等。
<path id="project.path">
<path refid="base.path"/>
<pathelement location="${ProjectName.componentName.classbindir}"/>
<pathelement location="${ProjectName.componentName.ejbjar.client}"/>
<pathelement
location="${ProjectName.referencesComponentName.classbindir}"/>
<pathelement location="${ProjectName.referencesComponentName.ejbjar.client}"/>
</path>
講解:此段定義專案中要用到的包檔案。
<path id="web.path">
<path refid="project.path"/>
<pathelement location="${servlet-lib.path}"/>
<pathelement location="${ejb-classes.dest}"/>
</path>
講解:此段定義在編譯servlet時的classpath,${ servlet-lib.path }是系統指定的Servlet引擎包。
為編譯作準備工作
<!--=============================================================== -->
<!-- Removes all created files and directories -->
<!-- ============================================================== -->
<target name="clean" depends="init">
<delete dir="${lib.dir}" />
<delete dir="${build.dir}" />
</target>
講解:清除build、lib目錄下的所有檔案和目錄。
<!-- ================================================================ -->
<!-- Makes sure the needed directory structure is in place -->
<!-- ================================================================ -->
<target name="prepare" depends="init,clean">
<mkdir dir="${lib.dir}" />
<mkdir dir="${lib.dir}/ejb" />
<mkdir dir="${lib.dir}/ejb/META-INF" />
<mkdir dir="${lib.dir}/web" />
<mkdir dir="${lib.dir}/web/WEB-INF" />
<mkdir dir="${lib.dir}/web/WEB-INF/classes" />
<mkdir dir="${lib.dir}/web/WEB-INF/lib" />
<mkdir dir="${lib.dir}/j2ee" />
<mkdir dir="${lib.dir}/META-INF" />
<mkdir dir="${lib.dir}/docs/api" />
<mkdir dir="${build.dir}" />
</target>
講解:建立build中要用到的所有目錄,根據需要可以加入自定義的目錄如:
<mkdir dir="${lib.dir}/javabean/ " />
編譯EJB部分
<!-- ================================================================ -->
<!-- Compilation of the EJB part of the application -->
<!-- ================================================================ -->
<target name="ejb-classes" depends="prepare">
<javac srcdir="${src.ejb.dir}"
destdir="${ejb-classes.dest}"
includes="com/**"
classpathref="base.path" />
</target>
講解:此小段用來完成編譯ejb和其它help classes。根據需要可以加入一個非常有用的元素:
encoding="${javac.encoding}"
<target name="ejb-meta-inf" depends="prepare">
<copy file="${etc.dir}/ejb-jar.xml"
tofile="${lib.dir}/ejb/META-INF/ejb-jar.xml" />
<copy file="${etc.dir}/jaws.xml"
tofile="${lib.dir}/ejb/META-INF/jaws.xml" />
<copy file="${etc.dir}/jboss.xml"
tofile="${lib.dir}/ejb/META-INF/jboss.xml" />
<copy file="${etc.dir}/jbosscmp-jdbc.xml"
tofile="${lib.dir}/ejb/META-INF/jbosscmp-jdbc.xml" />
</target>
講解:此小段用來拷貝EJB部署檔案,在JAS中EJB部署檔案有jaws.xml、jboss.xml、jbosscmp-jdbc.xml。
<target name="ejb-jar" depends="ejb-classes,ejb-meta-inf">
<jar jarfile="${build.dir}/${name}-ejb.jar"
basedir="${lib.dir}/ejb" />
</target>
講解:此小段用來把class和部署檔案壓縮成包檔案,這個包檔案就是一個EJB元件。
<target name="ejbclientjar" depends="ejb-jar,web-classes">
<copy
file="${ProjectName.referencesComponentName.home}/build/
${ProjectName.referencesComponentName.name}-ejb-client.jar"
tofile="${build.dir}/${ProjectName.referencesComponentName.name}
-ejb-client.jar" />
<jar jarfile="${build.dir}/${name}-ejb-client.jar"
basedir="${lib.dir}/ejb"
excludes="com/ProjectName/componentName/ejb/ComponentNameEJB.class" />
</target>
講解:此小段用來把class和部署檔案壓縮成包檔案,以支援客戶端執行。
編譯WEB部分
<!-- ================================================================== -->
<!-- Compilation of the web part of the application -->
<!-- ================================================================== -->
<target name="web-classes" depends="prepare,ejb-jar">
<javac srcdir="${src.servlet.dir}"
destdir="${lib.dir}/web/WEB-INF/classes"
includes="com/**"
classpath="${build.classpath}" />
</target>
講解:此小段用來完成編譯servlet。
<target name="web-web-inf" depends="prepare">
<copy file="${etc.dir}/jboss-web.xml"
tofile="${lib.dir}/web/WEB-INF/jboss-web.xml" />
<copy file="${etc.dir}/web.xml"
tofile="${lib.dir}/web/WEB-INF/web.xml" />
</target>
講解:此小段用來拷貝WEB部署檔案,在JAS中WEB部署檔案有jboss-web.xml。
<target name="war" depends="web-classes,web-web-inf">
<copy todir="${lib.dir}/web" >
<fileset dir="${src.web.dir}"/>
</copy>
<copy
file="${build.dir}/${ProjectName.referencesComponentName.name}-ejb-client.jar"
tofile="${lib.dir}/web/WEB-INF/lib/${ProjectName.referencesComponentName.name}
-ejb-client.jar" />
<jar jarfile="${build.dir}/${name}-web.war"
basedir="${lib.dir}/web" />
</target>
講解:此小段用來把所有的JSP程式、Html、Css、圖片和部署檔案等壓縮成WAR檔案。
編譯J2EE Application
<!-- ================================================================== -->
<!-- Compilation of the complete J2EE application (both web and EJB) -->
<!-- ================================================================== -->
<target name="j2ee-meta-inf" depends="prepare">
<copy file="${etc.dir}/application.xml"
tofile="${lib.dir}/j2ee/META-INF/application.xml" />
</target>
講解:此小段用來拷貝Application的部署檔案。
<target name="ear" depends="ejb-jar,war,j2ee-meta-inf">
<copy file="${build.dir}/${name}-ejb.jar"
tofile="${lib.dir}/j2ee/${name}-ejb.jar" />
<copy file="${build.dir}/${name}-web.war"
tofile="${lib.dir}/j2ee/${name}-web.war" />
<jar jarfile="${build.dir}/${name}.ear"
basedir="${lib.dir}/j2ee" />
</target>
講解:此小段用來把EJB元件、支援客戶端執行的包和部署檔案壓縮成EAR檔案,它就是一個J2EE Application。這裡要說明,在進行build時,根據需要可以不生成EAR檔案。
部署Application
<!-- ================================================================ -->
<!-- Deploy EAR file -->
<!-- ================================================================ -->
<target name="deploy-server" depends="ear,war">
<copy todir="${jboss.deploy}">
<fileset dir="${build.dir}" includes="*.ear">
</fileset>
</copy>
</target>
講解:此小段用來部署Application,在JAS3.0中${jboss.deploy}是JAS的熱部署目錄。
建立元件的API
<!-- =================================================================== -->
<!-- Create class and package usage pages -->
<!-- =================================================================== -->
<target name="docs" depends="init">
<javadoc locale="${javadoc.locale}" packagenames="${package.names}.${name}.*"
destdir="${javadoc.dir}"
classpath="${build.classpath}"
encoding="${javadoc.encoding}"
author="${javadoc.author}"
version="${javadoc.version}"
use="${javadoc.usage}"
windowtitle="${project.name} ${name} Component API"
doctitle="${project.name} ${name} Component"
bottom="Copyright ${sign.copyright} ${project.date}
${company.signature}. All Rights Reserved.">
<classpath >
<pathelement path="${lib.dir}/ejb"/>
</classpath>
<sourcepath>
<pathelement path="${src.main.dir}/ejb"/>
</sourcepath>
</javadoc>
</target>
講解:此小段用來建立元件的API。這裡強烈要求類設計人員和編碼人員按照Javadoc定義的標籤對原始碼進行註釋。
確定build的目標
<target name="startbanner">
<echo>+---------------------------------------+</echo>
<echo>+ Building ${name} Component +</echo>
<echo>+---------------------------------------+</echo>
</target>
<target name="endbanner" depends="main" >
<echo>+---------------------------------------+</echo>
<echo>+ Finished ${name} Component +</echo>
<echo>+---------------------------------------+</echo>
</target>
<target name="main" depends="startbanner, ejb-jar, ejbclientjar" />
<target name="main2" depends="startbanner, ejb-jar,
ejbclientjar,war" />
<target name="main3" depends="startbanner, ejb-jar,
ejbclientjar,war,ear,deploy-server" />
<target name="core" depends="ejb-war" />
<target name="ejb-war" depends="main2,endbanner" />
<target name="deploy" depends="main3,endbanner" />
<target name="all" depends="core, docs" />
講解:此小段用來確定build的目標。預設目錄為core,所以在build不加引數時,系統將只生成jar檔案和war檔案。如果 build時加上引數,系統將根據需要來生成檔案,例如:在命令列輸入ant deploy,系統將生成jar檔案、war檔案、ear檔案,同時將ear檔案進行部署。
eclipse中整合ant,建立工程舉例:
Eclipse中已經集成了Ant,我們可以直接在Eclipse中執行Ant。
以前面建立的Hello工程為例,建立以下目錄結構:
新建一個build.xml,放在工程根目錄下。build.xml定義了Ant要執行的批處理命令。雖然Ant也可以使用其它檔名,但是遵循標準能更使開發更規範,同時易於與別人交流。
通常,src存放Java原始檔,classes存放編譯後的class檔案,lib存放編譯和執行用到的所有jar檔案,web存放JSP等web檔案,dist存放打包後的jar檔案,doc存放API文件。
然後在根目錄下建立build.xml檔案,輸入以下內容:
Xml程式碼
<?xml version="1.0"?>
<project name="Hello world" default="doc">
<!-- properies -->
<property name="src.dir" value="src" />
<property name="report.dir" value="report" />
<property name="classes.dir" value="classes" />
<property name="lib.dir" value="lib" />
<property name="dist.dir" value="dist" />
<property name="doc.dir" value="doc"/>
<!-- 定義classpath -->
<path id="master-classpath">
<fileset file="${lib.dir}/*.jar" />
<pathelement path="${classes.dir}"/>
</path>
<!-- 初始化任務 -->
<target name="init">
</target>
<!-- 編譯 -->
<target name="compile" depends="init" description="compile the source files">
<mkdir dir="${classes.dir}"/>
<javac srcdir="${src.dir}" destdir="${classes.dir}" target="1.4">
<classpath refid="master-classpath"/>
</javac>
</target>
<!-- 測試 -->
<target name="test" depends="compile" description="run junit test">
<mkdir dir="${report.dir}"/>
<junit printsummary="on"
haltonfailure="false"
failureproperty="tests.failed"
showoutput="true">
<classpath refid="master-classpath" />
<formatter type="plain"/>
<batchtest todir="${report.dir}">
<fileset dir="${classes.dir}">
<include name="**/*Test.*"/>
</fileset>
</batchtest>
</junit>
<fail if="tests.failed">
***********************************************************
**** One or more tests failed! Check the output ... ****
***********************************************************
</fail>
</target>
<!-- 打包成jar -->
<target name="pack" depends="test" description="make .jar file">
<mkdir dir="${dist.dir}" />
<jar destfile="${dist.dir}/hello.jar" basedir="${classes.dir}">
<exclude name="**/*Test.*" />
<exclude name="**/Test*.*" />
</jar>
</target>
<!-- 輸出api文件 -->
<target name="doc" depends="pack" description="create api doc">
<mkdir dir="${doc.dir}" />
<javadoc destdir="${doc.dir}"
author="true"
version="true"
use="true"
windowtitle="Test API">
<packageset dir="${src.dir}" defaultexcludes="yes">
<include name="example/**" />
</packageset>
<doctitle><![CDATA[<h1>Hello, test</h1>]]></doctitle>
<bottom><![CDATA[<i>All Rights Reserved.</i>]]></bottom>
<tag name="todo" scope="all" description="To do:" />
</javadoc>
</target>
</project>
<span style="font-size:12px;"><span style="color:#3366ff;"><p style="margin-top: 0px; margin-bottom: 10px; padding-top: 0px; padding-bottom: 0px;"></p><p style="margin-top: 0px; margin-bottom: 10px; padding-top: 0px; padding-bottom: 0px;"></p></span></span>
以上xml依次定義了init(初始化),compile(編譯),test(測試),doc(生成文件),pack(打包)任務,可以作為模板。
選中Hello工程,然後選擇“Project”,“Properties”,“Builders”,“New…”,選擇“Ant Build”:
填入Name:Ant_Builder;Buildfile:build.xml;BaseDirectory:${workspace_loc: /Hello}(按“BrowseWorkspace”選擇工程根目錄),由於用到了junit.jar包,搜尋Eclipse目錄,找到 junit.jar,把它複製到Hello/lib目錄下,並新增到Ant的Classpath中:
然後在Builder面板中鉤上Ant_Build,去掉Java Builder:
再次編譯,即可在控制檯看到Ant的輸出:
Buildfile: F:\eclipse-projects\Hello\build.xml
init:
compile:
[mkdir] Created dir: F:\eclipse-projects\Hello\classes
[javac] Compiling 2 source files to F:\eclipse-projects\Hello\classes
test:
[mkdir] Created dir: F:\eclipse-projects\Hello\report
[junit] Running example.HelloTest
[junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.02 sec
pack:
[mkdir] Created dir: F:\eclipse-projects\Hello\dist
[jar] Building jar: F:\eclipse-projects\Hello\dist\hello.jar
doc:
[mkdir] Created dir: F:\eclipse-projects\Hello\doc
[javadoc] Generating Javadoc
[javadoc] Javadoc execution
[javadoc] Loading source files for package example...
[javadoc] Constructing Javadoc information...
[javadoc] Standard Doclet version 1.4.2_04
[javadoc] Building tree for all the packages and classes...
[javadoc] Building index for all the packages and classes...
[javadoc] Building index for all classes...
[javadoc] Generating F:\eclipse-projects\Hello\doc\stylesheet.css...
[javadoc] Note: Custom tags that could override future standardtags: @todo. To avoid potential overrides, use at least one periodcharacter (.) in custom tag names.
[javadoc] Note: Custom tags that were not seen: @todo
BUILD SUCCESSFUL
Total time: 11 seconds
Ant依次執行初始化,編譯,測試,打包,生成API文件一系列任務,極大地提高了開發效率。將來開發J2EE專案時,還可加入部署等任務。並且,即使脫離了Eclipse環境,只要正確安裝了Ant,配置好環境變數ANT_HOME=<Ant解壓目錄>, Path=…;%ANT_HOME%\bin,在命令列提示符下切換到Hello目錄,簡單地鍵入ant即可。
生成build.xml
Eclipse 自動生成 Ant的Build.xml 配置檔案,生成的方法很隱蔽
選擇你要生成Build.xml檔案的專案,右鍵. Export-> General -> Ant Buildfiles .
點Next,選擇專案,再點Finish.
生成完畢.
編寫build.xml
[html] view plaincopyprint?在CODE上檢視程式碼片派生到我的程式碼片
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- 每個構建檔案對應一個專案。<project>標籤時構建檔案的根標籤。它可以有多個內在屬性,就如程式碼中所示,其各個屬性的含義分別如下。
(1) default表示預設的執行目標,這個屬性是必須的。
(2) basedir表示專案的基準目錄。
(3) name表示專案名。
(4) description表示專案的描述。
-->
<project default="build" name="Sort">
<!-- 設定屬性或檔案路徑,讀取屬性使用${property},value路徑預設專案根目錄 -->
<property file="ant/builds.properties" />
<property name="src.dir" value="src/statics" />
<property name="classes.dir" value="ant/classes" />
<property name="lib.dir" value="lib" />
<property name="dist.dir" value="ant/dist" />
<!-- 定義classpath -->
<path id="master-classpath">
<fileset file="${lib.dir}/*.jar" />
<pathelement path="${classes.dir}" />
</path>
<!--一個專案標籤Project包含多個target標籤,一個target標籤可以依賴其他的target標籤
在生成可執行檔案之前必須先編譯該檔案,因策可執行檔案的target依賴於編譯程式的 target。
(1).name表示標明,這個屬性是必須的。
(2).depends表示依賴的目標。
(3)if表示僅當屬性設定時才執行。
(4)unless表示當屬性沒有設定時才執行。
(5)description表示專案的描述。
Ant的depends屬性指定了target的執行順序。Ant會依照depends屬性中target出現順序依次執行每個target。在執行之前,首先需要執行它所依賴的target。
-->
<!-- 初始化任務 -->
<target name="init">
<!-- 輸出標籤 ,${init}是builds.properties中的屬性 -->
<echo message=" Available Targets:"/>
<echo message="-------------------------------------------------------"/>
<echo message=" init ${init} ..."/>
<echo message="-------------------------------------------------------"/>
</target>
<!-- 編譯 -->
<target name="compile" depends="init" description="compile the source files">
<!-- 刪除資料夾 -->
<delete dir="${classes.dir}" />
<!-- 建立資料夾 -->
<mkdir dir="${classes.dir}" />
<!-- 編譯java生成class檔案 ,其屬性如下
(1).srcdir表示源程式的目錄。
(2).destdir表示class檔案的輸出目錄。
(3).include表示被編譯的檔案的模式。
(4).excludes表示被排除的檔案的模式。
(5).classpath表示所使用的類路徑。
(6).debug表示包含的除錯資訊。
(7).optimize表示是否使用優化。
(8).verbose 表示提供詳細的輸出資訊。
(9).fileonerror表示當碰到錯誤就自動停止。
-->
<javac srcdir="${src.dir}" destdir="${classes.dir}">
<!-- 編譯需要的jar包 引用前面設定的class-path -->
<classpath refid="master-classpath" />
</javac>
</target>
<!-- 打包成jar -->
<target name="pack" description="make .jar file">
<delete dir="${dist.dir}" />
<mkdir dir="${dist.dir}" />
<!-- 該標籤用來生成一個JAR檔案,其屬性如下
(1) destfile表示JAR檔名。
(2) basedir表示被歸檔的檔名。要操作的檔案路徑
(3) includes表示別歸檔的檔案模式。
(4) exchudes表示被排除的檔案模式。
-->
<jar destfile="${dist.dir}/hello.jar" basedir="${classes.dir}">
<!-- 不包含的類或內容 -->
<exclude name="**/*Test.*" />
</jar>
</target>
<!-- 生成zip壓縮包 -->
<target name="zip">
<delete dir="${release-dir}" />
<mkdir dir="${release-dir}" />
<!-- 該標籤用來生成一個zip檔案,其屬性如下
(1) destfile表示zip檔名。
(2) basedir表示被歸檔的檔名。 要操作的檔案路徑
(3) includes表示別歸檔的檔案模式。
(4) exchudes表示被排除的檔案模式。
-->
<zip destfile="${release-dir}/antTest.zip" update="true"
basedir="ant" />
</target>
</project>
ant教程詳解--javac,java,jar,war,delete,copy,mkdir:
Ant 的關鍵元素 ---結合例項分析
target 元素它為 Ant 的基本執行單元,它可以包含一個或多個具體的任務。多個 target 可以存在相互依賴關係。它有如下屬性:
1 ) name 屬性
指定 target 元素的名稱,這個屬性在一個 project 元素中是唯一的。我們可以通過指定 target 元素的名稱來指定某個 target 。
2 ) depends 屬性
用於描述 target 之間的依賴關係,若與多個 target 存在依賴關係時,需要以“ , ”間隔。 Ant 會依照 depends 屬性中 target 出現的順序依次執行每個 target 。被依賴的 target 會先執行。
3 ) if 屬性
用於驗證指定的屬性是否存在,若不存在,所在 target 將不會被執行。
4 ) unless 屬性
該屬性的功能與 if 屬性的功能正好相反,它也用於驗證指定的屬性是否存在,若不存在,所在 target 將會被執行。
5 ) description 屬性
該屬性是關於 target 功能的簡短描述和說明。
下面帶領讀者來看一個各屬性綜合使用的例子。修改 E:"build.xml 檔案,修改後的內容如下:
<? xml version="1.0" ?>
< project name ="targetStudy">
< target name ="targetA" if ="ant.java.version">
< echo message ="Java Version: ${ant.java.version}"/>
</ target >
< target name ="targetB" depends ="targetA" unless ="amigo">
< description >
a depend example!
</ description >
< echo message ="The base dir is: ${basedir}"/>
</ target >
</ project >
進入 E 盤後執行 ant targetB ,可看到如下圖所示的執行結果:
讀者分析結果後可以看到,我們執行的是名為 targetB 的 target ,因該 target 依賴於 targetA ,所以 targetA 將首先被執行,同時因為系統安裝了 java 環境,所以 ant.java.version 屬性存在,執行了 targetA 這個 target ,輸出資訊: [echo] Java Version: 1.5 , targetA 執行完畢後,接著執行 targetB ,因為 amigo 不存在,而 unless 屬性是在不存在時進入所在的 target 的,由此可知 targetB 得以執行,輸出資訊: The base dir is: E:" 。
property 元素
該元素可看作參量或者引數的定義, project 的屬性可以通過 property 元素來設定,也可在 Ant 之外設定。若要在外部引入某檔案,例如 build.properties 檔案,可以通過如下內容將其引入: <property file=” build.properties”/>
property 元素可用作 task 的屬性值。在 task 中是通過將屬性名放在“ ${ ”和“ } ”之間,並放在 task 屬性值的位置來實現的。
Ant 提供了一些內建的屬性,它能得到的系統屬性的列表與 Java 文件中 System.getPropertis() 方法得到的屬性一致,這些系統屬性可參考 sun 網站的說明。
同時, Ant 還提供了一些它自己的內建屬性,如下:
basedir : project 基目錄的絕對路徑,該屬性在講解 project 元素時有詳細說明,不再贅述;
ant.file : buildfile 的絕對路徑,如上面的各例子中, ant.file 的值為 E:"build.xml ;
ant.version : Ant 的版本,在本文中,值為 1.7.0 ;
ant.project.name :當前指定的 project 的名字,即前文說到的 project 的 name 屬性的值;
ant.java.version : Ant 檢測到的 JDK 的版本,在上例執行結果中可看到為 1.5 。
下面讓讀者來看一個 property 元素使用的簡單例子。修改 E:"build.xml 檔案,內容如下:
<? xml version="1.0" ?>
< project name ="propertyStudy" default ="example">
< property name ="name" value ="amigo"/>
< property name ="age" value ="25"/>
< target name ="example">
< echo message ="name: ${name}, age: ${age}"/>
</ target >
</ project >
該例的執行結果如下圖所示:由此讀者可以看出,通過如下兩個語句:
<property name="name" value="amigo"/>
<property name="age" value="25"/>
我們設定了名為 name 和 age 的兩個屬性,這兩個屬性設定後,讀者在下文中可以通過 ${name} 和 ${age} 分別取得這兩個屬性的值。
Ant 的常用任務
在 Ant 工具中每一個任務封裝了具體要執行的功能,是 Ant 工具的基本執行單位。在本小節中,主要引導讀者來看下 Ant 的常用任務及其使用舉例。
1. copy 任務
該任務主要用來對檔案和目錄的複製功能。舉例如下:
Eg1. 複製單個檔案: <copy file="file.txt" tofile="copy.txt"/>
Eg2. 對檔案目錄進行復制:
<copy todir="../newdir/dest_dir">
<fileset dir="src_dir"/>
</copy>
Eg3. 將檔案複製到另外的目錄:
<copy file="file.txt" todir="../other/dir"/>
2. delete 任務
對檔案或目錄進行刪除,舉例如下:
Eg1. 刪除某個檔案: <delete file="photo/amigo.jpg"/>
Eg2. 刪除某個目錄: <delete dir="photo"/>
Eg3. 刪除所有的備份目錄或空目錄:
<delete includeEmptyDirs="true">
<fileset dir="." includes="**/*.bak"/>
</delete>
3. mkdir 任務
建立目錄。 eg : <mkdir dir="build"/>
4. move 任務
移動檔案或目錄,舉例如下:
Eg1. 移動單個檔案: <move file="fromfile" tofile=”tofile”/>
Eg2. 移動單個檔案到另一個目錄: <move file="fromfile" todir=”movedir”/>
Eg3. 移動某個目錄到另一個目錄:
<move todir="newdir">
<fileset dir="olddir"/>
</move>
5. echo 任務
該任務的作用是根據日誌或監控器的級別輸出資訊。它包括 message 、 file 、 append 和 level 四個屬性,舉例如下:
<echo message="Hello,Amigo" file="logs/system.log" append="true">
利用 Ant 構建和部署 Java 工程
Ant 可以代替使用 javac 、 java 和 jar 等命令來執行 java 操作,從而達到輕鬆的構建和部署 Java 工程的目的。下面來看幾個知識點。
1. 利用 Ant 的 javac 任務來編譯 java 程式Ant 的 javac 任務用於實現編譯 Java 程式的功能。下面來看一個簡單的例子:
首先我們建立名為 antstudy 的 Java 工程,建立 src 目錄為原始碼目錄,在 src 目錄下建立 HelloWorld.java 這個類檔案。該類檔案的內容如下:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello,Amigo");
}
}
同時在 antstudy 工程的根目錄下建立 build.xml 檔案,在該檔案中編譯 src 目錄下的 java 檔案,並將編譯後的 class 檔案放入 build/classes 目錄中,在編譯前,需清除 classes 目錄,該檔案的內容如下:
<? xml version="1.0" ?>
< project name ="javacTest" default ="compile" basedir =".">
< target name ="clean">
< delete dir ="build"/>
</ target >
< target name ="compile" depends ="clean">
< mkdir dir ="build/classes"/>
< javac srcdir ="src" destdir ="build/classes"/>
</ target >
</ project >
執行該 build.xml 檔案,可在工程中看到新增了 build/classes 目錄,並在該目錄中生成了編譯後的 HelloWorld.class 檔案。
2. 使用 Ant 的 java 任務執行 Java 程式Ant 中可以使用 java 任務實現執行 Java 程式的功能。下面在 1 的例子中進行如下的修改,修改後的 build.xml 檔案的內容如下:
<? xml version="1.0" ?>
< project name ="javaTest" default ="jar" basedir =".">
< target name ="clean">
< delete dir ="build"/>
</ target >
< target name ="compile" depends ="clean">
< mkdir dir ="build/classes"/>
< javac srcdir ="src" destdir ="build/classes"/>
</ target >
< target name ="run" depends ="compile">
< java classname ="HelloWorld">
< classpath >
< pathelement path ="build/classes"/>
</ classpath >
</ java >
</ target >
</ project >
執行該 build.xml 檔案,可在控制檯看到 HelloWorld 的 main 方法的輸出。
3. 使用 Ant 的 jar 任務生成 jar 檔案讀者可以在上例的基礎上更進一步,來生成 jar 包,可在 run 這個 target 下再加上如下 target :
< target name ="jar" depends ="run">
< jar destfile ="helloworld.jar" basedir ="build/classes">
< manifest >
< attribute name ="Main-class" value ="HelloWorld"/>
</ manifest >
</ jar >
</ target >
此時將 ant 的 project 的 default 屬性設定為 jar ,同時執行該 build.xml 檔案,執行完畢後,可看到在工程目錄下生成了一個 jar 包 HelloWorld.jar 。
4. 使用 Ant 的 war 任務打包 J2EE Web 專案
建立一個 J2EE Web 工程,其目錄結構如下圖所示:
其中 src 為原始碼目錄, WebRoot 為各 jsp 存放目錄, lib 為工程的包目錄。在 antwebproject 工程目錄下建立了 build.xml 檔案,該檔案為該工程的 Ant 構件檔案。讀者可以 src 目錄下放入在前續例子中開發的 HelloWorld.java 檔案,並在 WebRoot 下建立 index.jsp 檔案,其內容很簡單,就是輸出 Hello 資訊,程式碼如下所示:
<% @ page language="java" contentType="text/html; charset="UTF-8" pageEncoding="UTF-8" %>
<! DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" >
< html >
< head >
< meta http-equiv ="Content-Type" content ="text/html; charset=ISO-8859-1">
< title > ant 打包測試 </ title >
</ head >
< body >
Hello,Ant
</ body >
</ html >
接下來編寫 build.xml 檔案,其內容如下:
<? xml version="1.0" ?>
< project name ="antwebproject" default ="war" basedir =".">
< property name ="classes" value ="build/classes"/>
< property name ="build" value ="build"/>
< property name ="lib" value ="WebRoot/WEB-INF/lib"/>
<!-- 刪除build 路徑-->
< target name ="clean">
< delete dir ="build"/>
</ target >
<!-- 建立build/classes 路徑,並編譯class 檔案到build/classes 路徑下-->
< target name ="compile" depends ="clean">
< mkdir dir ="${classes}"/>
< javac srcdir ="src" destdir ="${classes}"/>
</ target >
<!-- 打war 包-->
< target name ="war" depends ="compile">
< war destfile ="${build}/antwebproject.war" webxml ="WebRoot/WEB-INF/web.xml">
<!-- 拷貝WebRoot 下除了WEB-INF 和META-INF 的兩個資料夾-->
< fileset dir ="WebRoot" includes ="**/*.jsp"/>
<!-- 拷貝lib 目錄下的jar 包-->
< lib dir ="${lib}"/>
<!-- 拷貝build/classes 下的class 檔案-->
< classesdir ="${classes}"/>
</ war >
</ target >
</ project >
各 target 的作用在內容中已經進行說明,在此不再贅述。執行該 build 檔案,更新目錄後,可看到在 build 目錄下生成了 antwebproject.war 檔案,解開後可看到其目錄結構如下:
--META-INF
--MANIFEST.MF
--index.jsp
--WEB-INF
--lib
--log4j-1.2.9.jar
--classes
--HelloWorld.class
--web.xml
讀者可以將該 war 包拷貝到 Tomcat 的目錄下看一下執行結果。