一.背景 Maven2 的基本原理很簡(jiǎn)單,采用遠(yuǎn)程倉(cāng)庫(kù)和本地倉(cāng)庫(kù)以及 pom(project object model).xml ,將 pom.xml 中定義的 jar 文件從遠(yuǎn)程倉(cāng)庫(kù)下載到本地倉(cāng)庫(kù),各個(gè)應(yīng)用使用同一個(gè)本地倉(cāng)庫(kù)的 jar ,同一個(gè)版本的 jar 只需下載一次,而且避免每個(gè)應(yīng)用都去拷貝 jar 。如圖 1 。同時(shí)它采用了現(xiàn)在流行的插件體系架構(gòu),只保留最小的核心,其余功能都通過(guò)插件的形式提供,所以在執(zhí)行 maven 任務(wù)時(shí),才會(huì)自動(dòng)下載需要的插件。這個(gè)特性也為客戶系統(tǒng)的升級(jí)帶來(lái)的很大的方便,客戶每次升級(jí)的時(shí)候可以使用maven的遠(yuǎn)程部署功能自動(dòng)下載最新的系統(tǒng)組件(jar),并重新打包部署,很大程度的減少的系統(tǒng)升級(jí)的工作量。
理解Maven的原理,可以參考 Pear ――PHP擴(kuò)展與應(yīng)用庫(kù)( the PHP Extension and Application Repository ),其原理非常類似,都有一個(gè)官方庫(kù),都是微內(nèi)核,通過(guò)網(wǎng)絡(luò)將需要的文件下載到本地,通過(guò)官方倉(cāng)庫(kù)將相應(yīng)的類庫(kù)進(jìn)行統(tǒng)一管理。
Maven2的基本安裝方法網(wǎng)上很多,就到
http://maven.apache.org下載一個(gè)最新版,解壓后即可,如果需要在命令行運(yùn)行,還需要設(shè)置一些環(huán)境變量,網(wǎng)上的資料很多,這里就不多說(shuō)了??傊?,安裝成功后當(dāng)你在命令行下執(zhí)行maven -version后正確顯示當(dāng)前maven的版本即可。
我們?cè)陧?xiàng)目中結(jié)合maven的進(jìn)行開(kāi)發(fā)的主要思路:
1.建立支持Maven2的開(kāi)發(fā)框架,框架中結(jié)合了一些項(xiàng)目功能和工具類,并且此框架本身是一個(gè)eclipse工程,支持使用eclipse IDE的開(kāi)發(fā),并通過(guò)CVS可進(jìn)行團(tuán)隊(duì)協(xié)作。
2.在Maven2的pom.xml中制定開(kāi)發(fā)框架的依賴包,并建立依賴包的團(tuán)隊(duì)管理本地服務(wù)器,使團(tuán)隊(duì)中的包依賴得到統(tǒng)一管理。
3.每日下班后,在構(gòu)建服務(wù)器上每日從cvs上下載各個(gè)團(tuán)隊(duì)開(kāi)發(fā)人員的代碼,統(tǒng)一進(jìn)行集成構(gòu)建和測(cè)試。由于是每日構(gòu)建,所以發(fā)現(xiàn)的bug可及時(shí)反饋給開(kāi)發(fā)人員進(jìn)行修正,避免了一般開(kāi)發(fā)過(guò)程中的bug長(zhǎng)時(shí)間遺留的情況。
二.實(shí)施過(guò)程 為了實(shí)現(xiàn)上述思路,我們分幾步實(shí)施:
1.首先需要構(gòu)建一個(gè)系統(tǒng)的開(kāi)發(fā)框架,
我們有兩種方式構(gòu)建,
其一是從零開(kāi)始構(gòu)建全新的框架,進(jìn)入commond line,cd 到一個(gè)目錄 ,執(zhí)行
- mvn archetype:create -DgroupId=com.mycompany.app -DartifactId=my-webapp -DarchetypeArtifactId=maven-archetype-webapp
mvn archetype:create -DgroupId=com.mycompany.app -DartifactId=my-webapp -DarchetypeArtifactId=maven-archetype-webapp
執(zhí)行完畢后接下來(lái)cd 到項(xiàng)目目錄my-webapp下,執(zhí)行
- mvn package
- mvn eclipse:eclipse
mvn packagemvn eclipse:eclipse
之后,打開(kāi)eclipse,到其目錄下導(dǎo)入項(xiàng)目,并手動(dòng)編輯pom.xml文件,設(shè)定指定的jar包,比如加入一個(gè)jwebunit的jar包,我們需要在pom中添加一段:
- <dependency>
- <groupId>jwebunit</groupId>
- <artifactId>jwebunit</artifactId>
- <version>1.2</version>
- <scope>test</scope>
- <exclusions>
- <exclusion>
- <groupId>rhino</groupId>
- <artifactId>js</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
<dependency><groupId>jwebunit</groupId><artifactId>jwebunit</artifactId><version>1.2</version><scope>test</scope><exclusions><exclusion><groupId>rhino</groupId><artifactId>js</artifactId></exclusion></exclusions></dependency>
其中指定了包的名稱,版本,使用的范圍域等,pom.xml設(shè)置方式網(wǎng)上也是一堆一堆的,具體的可以自己搜搜。同時(shí)我們也可以使用maven2在 eclipse中的插件進(jìn)行編輯,很方便,就不用記住那些該死的標(biāo)簽了。插件下載地址
http://m2eclipse.codehaus.org /update,將這個(gè)url填入到eclipse的Help-》Software Updates->find&install中新建一個(gè)插件下載地址的對(duì)話框中即可下載。
這種方式是完全自定義一個(gè)全新的工程后再進(jìn)行框架搭建,比較累,尤其是添加依賴包的時(shí)候,需要根據(jù)自己的項(xiàng)目需要一個(gè)一個(gè)添加,很煩人,所以我們使用的第二個(gè)方法就直接找了一個(gè)現(xiàn)成的,到 Appfus 的網(wǎng)站
http://appfuse.org/ 根據(jù)項(xiàng)目需要下載了一個(gè)項(xiàng)目框架作為原型,我們使用的是appfuse-light-webwork-ibatis- 1.8.2(webwork2.26,spring2.0,ibatis2.0),如果你使用的是其他的的技術(shù),如 struts2,hibernate....直接到網(wǎng)站上下載一個(gè)相應(yīng)的框架即可。appfuse框架使用maven2作為基本構(gòu)建工具,其中自帶的 pom.xml也替開(kāi)發(fā)人員寫好了,中所定義的依賴包可滿足一般的開(kāi)發(fā)需要,如需要自己指定的包,那么直接在其pom.xml中添加即可。要將這個(gè)框架作為eclipse工程使用,需要在解壓后的框架目錄下執(zhí)行:
- mvn eclipse:eclipse -DdownloadSources=true
mvn eclipse:eclipse -DdownloadSources=true
這個(gè)命令會(huì)將工程將框架轉(zhuǎn)換為eclipse工程,并從遠(yuǎn)程下載jar包到本地倉(cāng)庫(kù)(window下是(C:\Documents and Settings\${username}\.m2\repository),之后執(zhí)行:
- mvn -Declipse.workspace=<path-to-eclipse-workspace> eclipse:add-maven-repo
mvn -Declipse.workspace=<path-to-eclipse-workspace> eclipse:add-maven-repo
其中path-to-eclipse-workspace是本機(jī)的eclipse的worksapce的路徑。執(zhí)行后maven會(huì)在eclipse中建立一個(gè)M2_REPO環(huán)境變量,并將其中所有的jar包引入到工程中,完全自動(dòng)化,十分方便。
打開(kāi)eclipse修改開(kāi)發(fā)中的環(huán)境變量(我們項(xiàng)目中使用了Myeclipse插件),找到相應(yīng)的工程,發(fā)現(xiàn)框架中已有一些代碼,這是appfuse提供給開(kāi)發(fā)人員的示例代碼,我們可以按照自己以前項(xiàng)目的積累進(jìn)行對(duì)框架進(jìn)行完善,形成一套自己的開(kāi)發(fā)框架,之后設(shè)置工程環(huán)境變量,在該項(xiàng)目中右鍵 ->Myeclipse->add web capabilities->指定該工作空間下的Src/main/webapps作為WEB工程的根路徑,并指定修改JAVA Build Path中
- src/main/java
- src/main/resource
- src/test/java
src/main/javasrc/main/resourcesrc/test/java
的三個(gè)soucrefolder的outputpath 為scr/main/webapp/WEB-Inf/class,這樣設(shè)置的目的是便于開(kāi)發(fā)人員在本地進(jìn)行部署測(cè)試,否則按照appfuse原有的工程設(shè)置是不能進(jìn)行順利部署的。
至此,我們已經(jīng)將Maven2結(jié)合到項(xiàng)目中,一開(kāi)始可能對(duì)目錄結(jié)構(gòu)有些不適應(yīng),畢竟這是maven提供的項(xiàng)目框架格式,可以修改為自己習(xí)慣的,但是不建議這樣做。設(shè)置完成后,cd到項(xiàng)目路徑下,運(yùn)行
- mvn test
- mvn package
- mvn install
mvn testmvn packagemvn install
三個(gè)命令,均成功后,可上傳到cvs/svn上面去,共享給項(xiàng)目組人員,各開(kāi)發(fā)人員可直接使用,但有可能M2_REPO環(huán)境設(shè)置路徑不一樣(C:\Documents and Settings\${username}\.m2\repository,畢竟不是所有人都把系統(tǒng)裝在C盤),需要手動(dòng)修改一下。
2.建立開(kāi)發(fā)團(tuán)隊(duì)內(nèi)部倉(cāng)庫(kù) 為了便于團(tuán)隊(duì)的依賴包管理,我們不能全部使用官網(wǎng)的倉(cāng)庫(kù),畢竟上面不具備我們項(xiàng)目開(kāi)發(fā)所需要的所有的依賴包,所以我們需要為自己的團(tuán)隊(duì)建立一個(gè)內(nèi)部倉(cāng)庫(kù),可以自己管理所需的依賴包,建立一個(gè)內(nèi)部倉(cāng)庫(kù)也十分簡(jiǎn)單(附錄中我們會(huì)使用artifactory進(jìn)行開(kāi)發(fā)內(nèi)部庫(kù)建立):
首先需要一個(gè) http server ,找臺(tái)服務(wù)器裝上 apache 就行。放一個(gè)空的 maven 目錄到 htdocs 下,假設(shè)服務(wù)器 ip 為 192.168.0.1 ,確認(rèn)能用
http://192.168.0.1/maven 訪問(wèn)到。
copy 本地倉(cāng)庫(kù)的jar包到服務(wù)器:對(duì)于 windows xp 來(lái)說(shuō)一般在 C:\Documents and Settings\ % username%\.m2 下,其中% username %為操作系統(tǒng)登錄用戶名。這時(shí)你可以看到 ${user.home}/.m2/ 下有個(gè) repository 目錄,里面有很多的項(xiàng)目相關(guān) jar ,目錄按 groupId/ artifactId/version 排好。把 repository 目錄整個(gè)拷貝到 apache 服務(wù)器的 maven 目錄下,如果需要官方缺少的 jar 或公司內(nèi)部 jar ,仿照這個(gè)目錄結(jié)構(gòu),做好 jar 放到 maven 目錄下?;蛘甙寻點(diǎn)opy到本地,運(yùn)行:
- mvn install:install-file -Dfile=X:/path/mail-1.3.jar -DartifactId=javamail -Dversion=1.3.1 -Dpackaging=jar -DgroupId=javamail
mvn install:install-file -Dfile=X:/path/mail-1.3.jar -DartifactId=javamail -Dversion=1.3.1 -Dpackaging=jar -DgroupId=javamail
開(kāi)發(fā)人員要使用內(nèi)部倉(cāng)庫(kù),只需修改本地工程pom.xml ,在 repository 配置后加上:
- <repository>
- <id>companyName</id>
- <url>http:
- </repository>
<repository><id>companyName</id><url>http:// ${ip}/maven</url></repository>
3.每日構(gòu)建 為了保證項(xiàng)目質(zhì)量,盡早的發(fā)現(xiàn)項(xiàng)目中的bug,我們需要每日對(duì)系統(tǒng)進(jìn)行構(gòu)建,這也是我們使用maven的初衷之一,maven的幾個(gè)命令就可幫助我們完成這項(xiàng)任務(wù),當(dāng)然我們可以使用持續(xù)構(gòu)建工具與maven結(jié)合實(shí)現(xiàn)定時(shí)自動(dòng)構(gòu)建。構(gòu)建方式:
- mvn test
- mvn package
- mvn install
mvn testmvn packagemvn install
maven 會(huì)自動(dòng)編譯,測(cè)試,運(yùn)行所有的testcase,這也要求我們的開(kāi)發(fā)人員一定要按照規(guī)則編寫單元測(cè)試代碼,否則每日構(gòu)建的意義就不大了。appfuse框架中提供了很好的單元測(cè)試代碼,包括針對(duì)數(shù)據(jù)庫(kù)層,業(yè)務(wù)邏輯層,web展示層等等,如果我們能很好的編寫這些單元測(cè)試,那么對(duì)于系統(tǒng)后續(xù)的缺陷管理和控制是大有裨益的。
構(gòu)建完成后或構(gòu)建時(shí)需要對(duì)最新版本的項(xiàng)目進(jìn)行部署,便于次日安排測(cè)試人員進(jìn)行測(cè)試,maven提供多多種部署方式,在pom.xml進(jìn)行項(xiàng)目的部署配置,不同的部署方式根據(jù)協(xié)議的不同,配置方式也有所差異:
以文件方式部署
- <project>
- [...]
- <distributionManagement>
- <repository>
- <id>proficio-repository</id>
- <name>Proficio Repository</name>
- <url>file:
- </repository>
- </distributionManagement>
- [...]
- </project>
<project>[...]<distributionManagement><repository><id>proficio-repository</id><name>Proficio Repository</name><url>file://${basedir}/target/deploy</url></repository></distributionManagement>[...]</project>
以SSH2方式部署
- <project>
- [...]
- <distributionManagement>
- <repository>
- <id>proficio-repository</id>
- <name>Proficio Repository</name>
- <url>scp:
- </repository>
- </distributionManagement>
- [...]
- </project>
<project>[...]<distributionManagement><repository><id>proficio-repository</id><name>Proficio Repository</name><url>scp://sshserver.yourcompany.com/deploy</url></repository></distributionManagement>[...]</project>
以SFTP方式部署
- <project>
- [...]
- <distributionManagement>
- <repository>
- <id>proficio-repository</id>
- <name>Proficio Repository</name>
- <url>sftp:
- </repository>
- </distributionManagement>
- [...]
- </project>
<project>[...]<distributionManagement><repository><id>proficio-repository</id><name>Proficio Repository</name><url>sftp://ftpserver.yourcompany.com/deploy</url></repository></distributionManagement>[...]</project>
以擴(kuò)展SSH方式部署
目前為止上述3中方式已經(jīng)被Maven包含,所以只要distributionManagement就可以了,但是使用擴(kuò)展SSH命令部署的話你不僅需要配置distributionManagement還需要一個(gè)build extension,如下
- <project>
- [...]
- <distributionManagement>
- <repository>
- <id>proficio-repository</id>
- <name>Proficio Repository</name>
- <url>scpexe:
- </repository>
- </distributionManagement>
- <build>
- <extensions>
- <extension>
- <groupId>org.apache.maven.wagon</groupId>
- <artifactId>wagon-ssh-external</artifactId>
- <version>1.0-alpha-6</version>
- </extension>
- </extensions>
- </build>
- [...]
- </project>
<project>[...]<distributionManagement><repository><id>proficio-repository</id><name>Proficio Repository</name><url>scpexe://sshserver.yourcompany.com/deploy</url></repository></distributionManagement><build><extensions><extension><groupId>org.apache.maven.wagon</groupId><artifactId>wagon-ssh-external</artifactId><version>1.0-alpha-6</version></extension></extensions></build>[...]</project>
The build extension specifies the use of the Wagon external SSH provider, which does the work of moving your files to the remote server. Wagon is the general purpose transport mechanism used throughout Maven.
以FTP方式部署
- <project>
- [...]
- <distributionManagement>
- <repository>
- <id>proficio-repository</id>
- <name>Proficio Repository</name>
- <url>[url]ftp:
- </repository>
- </distributionManagement>
- <build>
- <extensions>
- <extension>
- <groupId>org.apache.maven.wagon</groupId>
- <artifactId>wagon-ftp</artifactId>
- <version>1.0-alpha-6</version>
- </extension>
- </extensions>
- </build>
- [...]
- </project>
<project>[...]<distributionManagement><repository><id>proficio-repository</id><name>Proficio Repository</name><url>[url]ftp://ftpserver.yourcompany.com/deploy</url>[/url]</repository></distributionManagement><build><extensions><extension><groupId>org.apache.maven.wagon</groupId><artifactId>wagon-ftp</artifactId><version>1.0-alpha-6</version></extension></extensions></build>[...]</project>
一旦你配置好了相應(yīng)的POM你可以執(zhí)行下列命令來(lái)開(kāi)始部署:
mvn deploy
同時(shí)也可通過(guò)執(zhí)行一下命令生成此項(xiàng)目的站點(diǎn)報(bào)告,供項(xiàng)目參與人員使用。
mvn site
三. 結(jié)論
maven的強(qiáng)大顯而易見(jiàn),有很多其他的特性本文沒(méi)有提及,如對(duì)各類插件的支持,以及對(duì)項(xiàng)目模塊劃分和繼承關(guān)系的管理,這些都是maven的特性,也是 maven對(duì)項(xiàng)目生命周期的詳盡詮釋,有興趣深入的TX可以下載我在附件中提供的教程《Better Builds With Maven2》.同時(shí)我也提供我根據(jù)appfuse建立的一套項(xiàng)目框架,可在myeclipse環(huán)境下使用,大家可以共同探討完善。
附1:使用artifactory為Maven2團(tuán)隊(duì)開(kāi)發(fā)建立內(nèi)部開(kāi)發(fā)倉(cāng)庫(kù)詳解 在真正使用Maven后是為團(tuán)隊(duì)進(jìn)行定制,所以我們不應(yīng)使用官網(wǎng)的開(kāi)發(fā)庫(kù),應(yīng)在本地建立一個(gè)內(nèi)部開(kāi)發(fā)庫(kù)對(duì)團(tuán)隊(duì)的jar包進(jìn)行管理,所以我們首先搭建一個(gè)內(nèi)部庫(kù)環(huán)境,除文章上面所述的搭建Apache服務(wù)器方法外,我們還可以使用artifactory(下載地址:[url]http://www.jfrog.org/sites/artifactory /latest/[/url]),一個(gè)很好的maven內(nèi)部庫(kù)的應(yīng)用系統(tǒng),下載后執(zhí)行bin目錄下的artifactory.bat命令即可。啟動(dòng)后可訪問(wèn)控制臺(tái)http://內(nèi)部庫(kù)ip:8081/artifactory/驗(yàn)證服務(wù)是否成功啟動(dòng)。默認(rèn)的用戶名為admin,密碼為password。artifactory最重要的是可配置第三方j(luò)ar包,在deploy artifacts中加入并制定其groupId和artifactId即可
(不要忘記更改本地的pom.xml文件引入新加的jar包)。
在開(kāi)發(fā)端我們需要更改全局配置文件setting.xml文件,將工程中setting.xml放入本地maven2->conf目錄下,配置內(nèi)部倉(cāng)庫(kù)的地址,只需要在setting.xml的mirrors元素中加入以下配置:
- <mirror>
- <id>emay local</id>
- <mirrorOf>central</mirrorOf>
- <name>emay local artifactory</name>
- <url>http:
- </mirror>
<mirror><id>emay local</id><mirrorOf>central</mirrorOf><name>emay local artifactory</name><url>http://內(nèi)部庫(kù)ip:8081/artifactory/repo</url></mirror>
這里要注意的是,在加入這段代碼后我使用的appfuse框架中自帶的應(yīng)用服務(wù)器tomcat6進(jìn)行構(gòu)建,不能正常運(yùn)行,報(bào)tomcat出錯(cuò),把這段去掉或者在pom.xml中將應(yīng)用服務(wù)器改為tomcat5.5后運(yùn)行正常??磥?lái)maven還是有不少bug需要改進(jìn)。
配置完成后再運(yùn)行mvn install即可正常進(jìn)行構(gòu)建,maven會(huì)從本地內(nèi)部庫(kù)中尋找項(xiàng)目所依賴的jar包。運(yùn)行mvn clean清除maven生成文件。
附2:maven2命令大全 validate,驗(yàn)證工程是否正確,所有需要的資源是否可用。
compile,編譯項(xiàng)目的源代碼。
test-compile,編譯項(xiàng)目測(cè)試代碼。
test,使用已編譯的測(cè)試代碼,測(cè)試已編譯的源代碼。
package,已發(fā)布的格式,如jar,將已編譯的源代碼打包。
integration-test,在集成測(cè)試可以運(yùn)行的環(huán)境中處理和發(fā)布包。
verify,運(yùn)行任何檢查,驗(yàn)證包是否有效且達(dá)到質(zhì)量標(biāo)準(zhǔn)。
install,把包安裝在本地的repository中,可以被其他工程作為依賴來(lái)使用
deploy,在整合或者發(fā)布環(huán)境下執(zhí)行,將最終版本的包拷貝到遠(yuǎn)程的repository,使得其他的開(kāi)發(fā)者或者工程可以共享。
generate-sources,產(chǎn)生應(yīng)用需要的任何額外的源代碼,如xdoclet。