Maven 是一個(gè)軟件項(xiàng)目管理工具,它能夠管理一個(gè)項(xiàng)目生命周期中的構(gòu)建、文檔、報(bào)告、發(fā)布等。Websphere ApplicationServer Community Edition (簡(jiǎn)稱WASCE)是IBM發(fā)布的一款免費(fèi)的開(kāi)源 J2EE 應(yīng)用服務(wù)器。WASCE 構(gòu)建在Apache 社區(qū)開(kāi)發(fā)的 Geronimo 服務(wù)器的基礎(chǔ)之上,提供了更廣泛的硬件和軟件平臺(tái)的支持。在開(kāi)發(fā) J2EE項(xiàng)目時(shí),代碼的編譯、單元測(cè)試、文檔的生成以及把應(yīng)用部署到 WASCE 是一個(gè)煩瑣而且需要反復(fù)進(jìn)行的過(guò)程。本文展示了使用 Maven來(lái)管理項(xiàng)目,自動(dòng)化項(xiàng)目的構(gòu)建和到 WASCE 服務(wù)器的發(fā)布,提高項(xiàng)目的開(kāi)發(fā)效率。
Maven 是 Apache 開(kāi)源社區(qū)開(kāi)發(fā)的用于簡(jiǎn)化 Java 軟件項(xiàng)目構(gòu)建的工具,它是在 Java項(xiàng)目構(gòu)建領(lǐng)域的成熟理論和豐富經(jīng)驗(yàn)的基礎(chǔ)之上,以高度重用的形式提供給開(kāi)發(fā)者。Maven的目標(biāo)是要使得項(xiàng)目的構(gòu)建更加容易,它把編譯、打包、測(cè)試、發(fā)布等開(kāi)發(fā)過(guò)程中的不同環(huán)節(jié)有機(jī)的串聯(lián)了起來(lái),并產(chǎn)生一致的、高質(zhì)量的項(xiàng)目信息,使得項(xiàng)目成員能夠及時(shí)地得到反饋。
在使用 Maven 的過(guò)程中,會(huì)經(jīng)常遇到以下概念,了解這些有助于更好的理解 Maven 的構(gòu)建過(guò)程。
1. Project:Maven 把它所要構(gòu)建的任何項(xiàng)目都稱為一個(gè) Project。此 Project 應(yīng)該符合下面定義的POM模型。一個(gè)Project 可以依賴于另一個(gè) Project;Project 還可以包含多個(gè)子 Project,子 Project 也是一個(gè)獨(dú)立的Project。Maven 可以管理 Project 之間的各種關(guān)系。
2. Project Object Model(POM):POM 定義了 Project 的元數(shù)據(jù)。Maven 可以根據(jù)這些元數(shù)據(jù)來(lái)構(gòu)建這個(gè) Project。POM一般定義在 Project 根目錄下的 project.xml 文件中。
3. Dependency:一般的 Java 項(xiàng)目在編譯或運(yùn)行時(shí)需要依賴于外部的包,在 Maven 中,這些包稱為 Dependency。
4. Goal:Goal 是 Maven 中的執(zhí)行單元,相當(dāng)于 Ant 中的 task。每一個(gè) Goal都對(duì)應(yīng)于項(xiàng)目構(gòu)建過(guò)程中的一個(gè)操作,例如:Java 程序的編譯、web 應(yīng)用打包。Maven 通過(guò) Plug-in的方式已經(jīng)提供了大多數(shù)需要經(jīng)常使用的 Goal,但對(duì)應(yīng)特定的項(xiàng)目,也可以在 maven.xml 中定義自己的 Goal。
5. Plug-in:Maven 是通過(guò) Plug-in 來(lái)組織的。Maven 所提供的每一項(xiàng)功能都是通過(guò) Plug-in來(lái)完成的。Plug-in 是可以重用的,它定義了 Goal,并且使用在 POM 中定義的 Project 元數(shù)據(jù)來(lái)執(zhí)行這些 Goal。
6. Repository:Repository 用來(lái)統(tǒng)一存放 Maven 在構(gòu)建項(xiàng)目過(guò)程中所依賴的外部的包文件。有兩中類型的Repository:Local Repository 和 Remote Repository。Maven 在構(gòu)建過(guò)程中,會(huì)檢查 LocalRepository,如果沒(méi)有所依賴的包,會(huì)去檢查 Remote Repository,并且把此包自動(dòng)下載到 Local Repository。
第一次接觸 Maven 的開(kāi)發(fā)人員一般都存在困惑:我們已經(jīng)有 Ant 了,問(wèn)什么還需要 Maven?我們可以從一個(gè)項(xiàng)目的開(kāi)發(fā)、管理和構(gòu)建過(guò)程來(lái)回答這個(gè)問(wèn)題。
下面假設(shè)我們有一個(gè)項(xiàng)目為 SampleApp1,首先我們使用 Ant 作為構(gòu)建工具,需要進(jìn)行的工作如下:
1. 規(guī)劃 SampleApp1 項(xiàng)目,包括用來(lái)存放不同資源的目錄結(jié)果,需要使用的外部包文件等。
2. 編寫(xiě) build.xml。在 build.xml中,項(xiàng)目的定義信息(比如目錄信息和外部包依賴信息)和構(gòu)建步驟混合在一起。這樣的一個(gè)顯著缺點(diǎn)是對(duì)項(xiàng)目 SampleApp2,build.xml完全沒(méi)有可重用性。例如我們需要對(duì)一個(gè) web 應(yīng)用打包,就需要在 build.xml 中進(jìn)行如下定義:
<target name="war" depends="init"> <war destfile="Filter.war" webxml="${filter}/WEB-INF/web.xml" compress="false"> <classes dir="${dest}"> <include name="**/*.*"/> </classes> <fileset dir="${filter}"> <include name="**/*.*"/> </fileset> </war> </target> |
3. 運(yùn)行 Ant 構(gòu)建項(xiàng)目。
下面我們?cè)倏词褂?Maven 作為項(xiàng)目管理工具,需要進(jìn)行如下工作:
1. 運(yùn)行如下命令來(lái)生成可以用 Maven 來(lái)管理的項(xiàng)目 SampleApp1:
maven genapp |
此命令生成了 SampleApp1 的原型,可以在此基礎(chǔ)上添加自己的資源。
2. 修改 project.xml。此文件只包含項(xiàng)目定義信息,比如目錄信息、外部包依賴、測(cè)試信息、報(bào)告等。Maven plug-in可以根據(jù)這些信息來(lái)構(gòu)建項(xiàng)目。對(duì)于上面例子中對(duì) web 應(yīng)用打包的操作,在 Maven 中有一個(gè) plug-in可以完成此操作,我們不需要再重新定義,只需要調(diào)用如下命令:
maven war |
3. 運(yùn)行 maven 構(gòu)建項(xiàng)目。
從以上比較可以看出,主要的差別在第二步。Maven 通過(guò) POM,把項(xiàng)目元數(shù)據(jù)和項(xiàng)目構(gòu)建過(guò)程定義分離開(kāi)來(lái),使項(xiàng)目構(gòu)建過(guò)程定義可以得到充分重用??梢哉J(rèn)為 Ant 是"拷貝-粘貼"形式的重用,而 Maven 是通過(guò) plug-in 方式實(shí)現(xiàn)了真正的重用。
除了重用性,Maven 還提供了其它特性,例如 Repository 機(jī)制,依賴管理等;而且還包含大量的可以重用的 Plug-in。
Geronimo 社區(qū)為了方便J2EE應(yīng)用的開(kāi)發(fā)和部署,開(kāi)發(fā)了一套 Maven Plug-in,從而使得 Maven 可以用在基于Geronimo 的項(xiàng)目的整個(gè)構(gòu)建過(guò)程中。WASCE 構(gòu)建在 Geronimo 基礎(chǔ)之上,所以這套 Plug-in 也完全適用于 WASCE。
Geronimo 部署 Plug-in 可以啟動(dòng)和停止 WASCE 服務(wù)器、部署和卸載一個(gè)應(yīng)用、啟動(dòng)和停止一個(gè)應(yīng)用。
這個(gè) Plug-in 主要包含以下命令:
以上參數(shù)描述如下:
uri:用于連接到服務(wù)器的 URI。此 URI 采用如下形式:deployer:Geronimo:jmx://host:port。
username:連接到服務(wù)器的管理員的用戶名,默認(rèn)情況下是 system。
password:連接到服務(wù)器的管理員的口令,默認(rèn)情況下是 manager。
module:要部署的應(yīng)用的文件路徑。
plan:要部署的應(yīng)用的部署描述文件的路徑,此參數(shù)為可選項(xiàng)。
id:所部署的應(yīng)用的 configId。
下面我們將通過(guò)一個(gè)例子 Arithmetic Example 來(lái)展示 Maven 在 WASCE 開(kāi)發(fā)中的應(yīng)用。此例子的源程序在后面可以下載。
Arithmetic Example 是一個(gè)簡(jiǎn)單的計(jì)數(shù)器應(yīng)用程序。為了只關(guān)注于 Maven 的使用,此應(yīng)用只使用了 Servlet 和 JSP。此應(yīng)用包括3個(gè)頁(yè)面
圖1是這些頁(yè)面之間的流程圖。
Maven 提供了一個(gè)名為 Genapp 的 Plug-in,它可以生成項(xiàng)目框架,簡(jiǎn)化項(xiàng)目的配置。運(yùn)行此 Plug-in 時(shí),它會(huì)詢問(wèn)用戶一些信息,并且根據(jù)這些信息生成項(xiàng)目。主要詢問(wèn)的信息包括以下內(nèi)容:
1. 要使用的項(xiàng)目模板。此 Plug-in 包括7種項(xiàng)目模板,經(jīng)常用的包括默認(rèn)模板、web 應(yīng)用模板、ejb 應(yīng)用模板、struts 應(yīng)用模板。Arithmetic Example 使用 web 應(yīng)用模板。
2. 此應(yīng)用的ID。此 ID 用來(lái)表示生成的包文件的名字。
3. 此應(yīng)用的名字。此項(xiàng)目的一個(gè)簡(jiǎn)單描述。
4. 此應(yīng)用的包名字。指定此應(yīng)用最上層的包名字。Arithmetic Example 使用com.arithmetic.example。
Maven 還提供了一個(gè)名為 Eclipse 的 Plug-in,它可以把 Maven 項(xiàng)目生成 Eclipse 工程。這樣就可以利用 Eclipse 提供的強(qiáng)大的集成開(kāi)發(fā)環(huán)境來(lái)開(kāi)發(fā)我們的項(xiàng)目。
在生成 Eclipse 工程的過(guò)程中,可能需要從 Remote Repository 上下載一些本項(xiàng)目所依賴的包文件。
可以在 Eclipse 中把生成的工程導(dǎo)入進(jìn)來(lái),這時(shí)會(huì)發(fā)現(xiàn)有一些錯(cuò)誤提示,這是因?yàn)樯傻墓こ汤镉玫搅艘粋€(gè) Classpath 變量MAVEN_REPO,此變量指向 Maven 在本地機(jī)器上的 Repository 目錄,在 windows 平臺(tái),此變量的值一般為C:\Documents and Settings\Administrator\.maven\repository。可以通過(guò)arithexample 工程的屬性設(shè)置來(lái)添加此變量,如圖2所示。
設(shè)置完 MAVEN_REPO,就可以在 Eclipse 中編寫(xiě)所需要的 Servlet 和 JSP 了。
Arithmetic Example 的構(gòu)建過(guò)程主要包括以下幾步:
1. 源程序的編譯。
2. 打包成 WAR 文件。
3. 部署到 WAS CE 服務(wù)器。
4. 啟動(dòng) Arithmetic Example 應(yīng)用。
對(duì)應(yīng)第一步和第二步,Maven 已經(jīng)提供了相應(yīng)的 Goal。第三步和第四步,需要使用 Geronimo 部署 Plug-in提供的命令來(lái)編寫(xiě)自己的 Goal。對(duì)于特定于某一個(gè)項(xiàng)目的 Goal 需要定義在此項(xiàng)目根目錄下的 maven.xml 中,在 ArithmeticExample 的 maven.xml 中,我們定義了以下 Goal:
1. deploy:部署 Arithmetic Example 到 Geronimo 服務(wù)器。
2. start:?jiǎn)?dòng)部署的 Arithmetic Example 應(yīng)用。
3. stop:停止部署的 Arithmetic Example 應(yīng)用。
4. undeploy0:卸載部署的 Arithmetic Example 應(yīng)用。
5. default:是一個(gè)默認(rèn) Goal,當(dāng)運(yùn)行 Maven 而不指定 Goal 時(shí),將會(huì)運(yùn)行此 Goal。此 Goal 將會(huì)編譯源程序、打包應(yīng)用成 WAR 文件、部署應(yīng)用以及啟動(dòng)應(yīng)用。
6. undeploy:此 Goal 停止 Arithmetic Example 應(yīng)用,然后卸載此應(yīng)用。
7. redeploy:此 Goal 先運(yùn)行 undeploy,再運(yùn)行 default。
<?xml version="1.0" encoding="UTF-8"?> <project default="default" xmlns:j="jelly:core" xmlns:u="jelly:util" xmlns:ant="jelly:ant" xmlns:velocity="jelly:velocity" xmlns:deploy="geronimo:deploy"> <goal name="default" prereqs="war,deploy,start"/> <goal name="undeploy" prereqs="stop,undeploy0"/> <goal name="redeploy" prereqs="undeploy,default"/> <preGoal name="java:compile"> <mkdir dir="${maven.build.dir}/xdoclet/webdoclet/WEB-INF" /> <attainGoal name="xdoclet:webdoclet" /> </preGoal> <goal name="deploy"> <deploy:distribute uri="deployer:geronimo:jmx" username="${geronimo.admin.user}" password="${geronimo.admin.password}" module="${module.file}"/> </goal> <goal name="start"> <deploy:start uri="deployer:geronimo:jmx" username="${geronimo.admin.user}" password="${geronimo.admin.password}" id="${module.configId}"/> </goal> <goal name="stop"> <deploy:stop uri="deployer:geronimo:jmx" username="${geronimo.admin.user}" password="${geronimo.admin.password}" id="${module.configId}"/> </goal> <goal name="undeploy0"> <deploy:undeploy uri="deployer:geronimo:jmx" username="${geronimo.admin.user}" password="${geronimo.admin.password}" id="${module.configId}"/> </goal> </project> |
聯(lián)系客服