Maven的安裝、配置及使用入門(原文轉載)


本書代碼下載 

大家可以從我的網站下載本書的代碼:http://www.juvenxu.com/mvn-in-action/,也可以通過我的網站與我取得聯繫,歡迎大家與我交流任何關於本書的問題和關於Maven的問題。 

咖啡與工具 
本書相當一部分的內容是在蘇州十全街邊的Solo咖啡館完成的,老闆Yin親手烘焙咖啡豆、並能做出據說是蘇州最好的咖啡,這小橋流水畔的溫馨小 屋能夠幫我消除緊張和焦慮,和Yin有一句沒一句的聊天也是相當的輕鬆。Yin還教會了我如何自己研磨咖啡豆、手衝滴率咖啡,讓我能夠每天在家裏也能享受 香氣四溢的新鮮咖啡。 
本書的書稿是使用Git和Unfuddle(http://unfuddle.com/)進行管理的,書中的大量截圖是通過Jing(http://www.techsmith.com/jing/)製作的。 
JuvenXu 
2010年10月於蘇州Solo咖啡 


致謝 
感謝費曉峯,是你最早讓我學習使用Maven,並在我開始學習的過程中給予了不少幫助。 
感謝Maven開源社區特別是Maven的創立者Jason Van Zyl,是你們一起創造瞭如此優秀的開源工具,造福了全世界這麼多的開發人員。 
感謝我的家人,一年來,我的大部分原來屬於你們的業餘時間都給了這本書,感謝你們的理解和支持。 
感謝二少、Garin、Sutra、JTux、紅人、linux_china、Chris、Jdonee、zc0922、還有很多Maven中文社區的朋友,你們給了本書不少建議,並在我寫作過程中不斷鼓勵我和支持我,你們是我寫作最大的動力之一。 
最後感謝本書的策劃編輯楊福川和曾珊,我從你們身上學到了很多,你們是最專業的、最棒的。

第1章 Maven簡介 Top

1.1  何爲Maven/2

1.2  爲什麼需要Maven/4

1.3  Maven與極限編程/7
1.4  被誤解的Maven/8
1.5  小結/9

1.1 何爲Maven Top

Maven這個詞可以翻譯爲“知識的積累”,也可以翻譯爲“專 家”或“內行”。本書將介紹Maven這一跨平臺的項目管理工具。作爲Apache組織中的一個頗爲成功的開源項目,Maven主要服務於基於Java平 臺的項目構建、依賴管理和項目信息管理。無論是小型的開源類庫項目,還是大型的企業級應用;無論是傳統的瀑布式開發,還是流行的敏捷模式,Maven都能 大顯身手。

1.1.1  何爲構建

不管你是否意識到,構建(build)是每一位程序員每天都在做的工作。早上來 到公司,我們做的第一件事情就是從源碼庫簽出最新的源碼,然後進行單元測試,如果發現失敗的測試,會找相關的同事一起調試,修復錯誤代碼。接着回到自己的 工作上來,編寫自己的單元測試及產品代碼,我們會感激IDE隨時報出的編譯錯誤提示。
忙到午飯時間,代碼編寫得差不多了,測試也通過了,開心地享 用午餐,然後休息。下午先在昏昏沉沉中開了個例會,會議結束後喝杯咖啡繼續工作。剛纔在會上經理要求看測試報告,於是找了相關工具集成進IDE,生成了像 模像樣的測試覆蓋率報告,接着發了一封電子郵件給經理,鬆了口氣。誰料QA小組又發過來了幾個bug,沒辦法,先本地重現再說,於是熟練地用IDE生成了 一個WAR包,部署到Web容器下,啓動容器。看到熟悉的界面了,遵循bug報告,一步步重現了bug……快下班的時候,bug修好了,提交代碼,通知 QA小組,在愉快中結束了一天的工作。

仔細總結一下,我們會發現,除了編寫源代碼,我們每天有相當一部分時間花在了編 譯、運行單元測試、生成文檔、打包和部署等煩瑣且不起眼的工作上,這就是構建。如果我們現在還手工這樣做,那成本也太高了,於是有人用軟件的方法讓這一系 列工作完全自動化,使得軟件的構建可以像全自動流水線一樣,只需要一條簡單的命令,所有煩瑣的步驟都能夠自動完成,很快就能得到最終結果。

1.1.2  Maven是優秀的構建工具

前面介紹了Maven的用途之一是服務於構建,它是一個異常強大的構建工具,能 夠幫我們自動化構建過程,從清理、編譯、測試到生成報告,再到打包和部署。我們不需要也不應該一遍又一遍地輸入命令,一次又一次地點擊鼠標,我們要做的是 使用Maven配置好項目,然後輸入簡單的命令(如mvn clean install),Maven會幫我們處理那些煩瑣的任務。

Maven是跨平臺的,這意味着無論是在Windows上,還是在Linux或者Mac上,都可以使用同樣的命令。

我們一直在不停地尋找避免重複的方法。設計的重複、編碼的重複、文檔的重複,當 然還有構建的重複。Maven最大化地消除了構建的重複,抽象了構建生命週期,並且爲絕大部分的構建任務提供了已實現的插件,我們不再需要定義過程,甚至 不需要再去實現這些過程中的一些任務。最簡單的例子是測試,我們沒必要告訴Maven去測試,更不需要告訴Maven如何運行測試,只需要遵循Maven 的約定編寫好測試用例,當我們運行構建的時候,這些測試便會自動運行。

想象一下,Maven抽象了一個完整的構建生命週期模型,這個模型吸取了大量其 他的構建腳本和構建工具的優點,總結了大量項目的實際需求。如果遵循這個模型,可以避免很多不必要的錯誤,可以直接使用大量成熟的Maven插件來完成我 們的任務(很多時候我們可能都不知道自己在使用Maven插件)。此外,如果有非常特殊的需求,我們也可以輕鬆實現自己的插件。

Maven還有一個優點,它能幫助我們標準化構建過程。在Maven之前,十個項目可能有十種構建方式;有了Maven之後,所有項目的構建命令都是簡單一致的,這極大地避免了不必要的學習成本,而且有利於促進項目團隊的標準化。

綜上所述,Maven作爲一個構建工具,不僅能幫我們自動化構建,還能夠抽象構建過程,提供構建任務實現;它跨平臺,對外提供了一致的操作接口,這一切足以使它成爲優秀的、流行的構建工具。

1.1.3  Maven不僅僅是構建工具

Java不僅是一門編程語言,還是一個平臺,通過JRuby和Jython,我 們可以在Java平臺上編寫和運行Ruby和Python程序。我們也應該認識到,Maven不僅是構建工具,還是一個依賴管理工具和項目信息管理工具。 它提供了中央倉庫,能幫我們自動下載構件。

在這個開源的年代裏,幾乎任何Java應用都會借用一些第三方的開源類庫,這些 類庫都可通過依賴的方式引入到項目中來。隨着依賴的增多,版本不一致、版本衝突、依賴臃腫等問題都會接踵而來。手工解決這些問題是十分枯燥的,幸運的是 Maven提供了一個優秀的解決方案,它通過一個座標系統準確地定位每一個構件(artifact),也就是通過一組座標Maven能夠找到任何一個 Java類庫(如jar文件)。Maven給這個類庫世界引入了經緯,讓它們變得有秩序,於是我們可以藉助它來有序地管理依賴,輕鬆地解決那些繁雜的依賴 問題。

Maven還能幫助我們管理原本分散在項目中各個角落的項目信息,包括項目描 述、開發者列表、版本控制系統地址、許可證、缺陷管理系統地址等。這些微小的變化看起來很瑣碎,並不起眼,但卻在不知不覺中爲我們節省了大量尋找信息的時 間。除了直接的項目信息,通過Maven自動生成的站點,以及一些已有的插件,我們還能夠輕鬆獲得項目文檔、測試報告、靜態分析報告、源碼版本日誌報告等 非常具有價值的項目信息。

Maven還爲全世界的Java開發者提供了一個免費的中央倉庫,在其中幾乎可以找到任何的流行開源類庫。通過一些Maven的衍生工具(如Nexus),我們還能對其進行快速地搜索。只要定位了座標,Maven就能夠幫我們自動下載,省去了手工勞動。

使用Maven還能享受一個額外的好處,即Maven對於項目目錄結構、測試用 例命名方式等內容都有既定的規則,只要遵循了這些成熟的規則,用戶在項目間切換的時候就免去了額外的學習成本,可以說是約定優於配置 (Convention Over Configuration)。

1.2 爲什麼需要Maven Top

Maven不是Java領域唯一的構建管理的解決方案。本節將通過一些簡單的例子解釋Maven的必要性,並介紹其他構建解決方案,如IDE、Make和Ant,並將它們與Maven進行比較。

1.2.1  組裝PC和品牌PC

筆者初中時開始接觸計算機,到了高中時更是夢寐以求希望擁有一臺自己的計算機。我的第一臺計算機是賽揚733的,選購是一個漫長的過程,我先閱讀了大量的雜誌以瞭解各類配件的優劣,CPU、內存、主板、顯卡,甚至聲卡,我都仔細地挑選,後來還跑了很多商家,調貨、討價還價,組裝好後自己裝操作系統和驅動程序……雖然這花費了我大量時間,但我很享受這個過程。可是事實證明,裝出來的機器穩定性不怎麼好。

一年前我需要配一臺工作站,這時候我已經沒有太多時間去研究電腦配件了。我選擇了某知名PC供應商的在線商店,大概瀏覽了一下主流的機型,選擇了我需要的配置,然後下單、付款。接着PC供應商幫我組裝電腦、安裝操作系統和驅動程序。一週後,物流公司將電腦送到我的家裏,我接上顯示器、電源、鼠標和鍵盤就能直接使用了。這爲我節省了大量時間,而且這臺電腦十分穩定,商家在把電腦發送給我之前已經進行了很好的測試。對了,我還能享受兩年的售後服務。

使用腳本建立高度自定義的構建系統就像買組裝PC,耗時費力,結果也不一定很好。當然,你可以享受從無到有的樂趣,但恐怕實際項目中無法給你那麼多時間。使用Maven就像購買品牌PC,省時省力,並能得到成熟的構建系統,還能得到來自於Maven社區的大量支持。唯一與購買品牌PC不同的是,Maven是開源的,你無須爲此付費。如果有興趣,你還能去了解Maven是如何工作的,而我們無法知道那些PC巨頭的商業祕密。

1.2.2  IDE不是萬能的

當然,我們無法否認優秀的IDE能大大提高開發效率。當前主流的IDE如Eclipse和NetBeans等都提供了強大的文本編輯、調試甚至重構功能。雖然使用簡單的文本編輯器和命令行也能完成絕大部分開發工作,但很少有人願意那樣做。然而,IDE是有其天生缺陷的:

  • IDE依賴大量的手工操作。編譯、測試、代碼生成等工作都是相互獨立的,很難一鍵完成所有工作。手工勞動往往意味着低效,意味着容易出錯。
  • 很難在項目中統一所有的IDE配置,每個人都有自己的喜好。也正是由於這個原因,一個在機器A上可以成功運行的任務,到了機器B的IDE中可能就會失敗。

我們應該合理利用IDE,而不是過多地依賴它。對於構建這樣的任務,在IDE中一次次地點擊鼠標是愚蠢的行爲。Maven是這方面的專家,而且主流IDE都集成了Maven,我們可以在IDE中方便地運行Maven執行構建。

1.2.3  Make

Make也許是最早的構建工具,它由Stuart Feldman於1977年在Bell實驗室創建。Stuart Feldman也因此於2003年獲得了ACM國際計算機組織頒發的軟件系統獎。目前Make有很多衍生實現,包括最流行的GNU Make和BSD Make,還有Windows平臺的Microsoft nmake等。

Make由一個名爲Makefile的腳本文件驅動,該文件使用Make自己定義的語法格式。其基本組成部分爲一系列規則(Rules),而每一條規則又包括目標(Target)、依賴(Prerequisite)和命令(Command)。Makefile的基本結構如下:

  1. <span style="font-size: small;">TARGET… : PREREQUISITE…  
  2. COMMAND  
  3. …  
  4. …  
  5. </span>  

     Make通過一系列目標和依賴將整個構建過程串聯起來,同時利用本地命令完成每個目標的實際行爲。Make的強大之處在於它可以利用所有系統的本地命令,尤其是UNIX/Linux系統,豐富的功能、強大的命令能夠幫助Make快速高效地完成任務。

但是,Make將自己和操作系統綁定在一起了。也就是說,使用Make,就不能實現(至少很難)跨平臺的構建,這對於Java來說是非常不友好的。此外,Makefile的語法也成問題,很多人抱怨Make構建失敗的原因往往是一個難以發現的空格或Tab使用錯誤。

1.2.4  Ant

Ant不是指螞蟻,而是意指“另一個整潔的工具”(Another Neat Tool),它最早用來構建著名的Tomcat,其作者James Duncan Davidson創作它的動機就是因爲受不了Makefile的語法格式。我們可以將Ant看成是一個Java版本的Make,也正因爲使用了Java,Ant是跨平臺的。此外,Ant使用XML定義構建腳本,相對於Makefile來說,這也更加友好。

與Make類似,Ant有一個構建腳本build.xml,如下所示:

<?xml version="1.0"?>

<project name="Hello" default="compile">

<target name="compile" description="compile the Java source code to class files">

<mkdir dir="classes"/>

<javac srcdir="." destdir="classes"/>

</target>

<target name="jar" depends="compile" description="create a Jar file ">

<jar destfile="hello.jar">

<fileset dir="classes" includes="**/*.class"/>

<manifest>

<attribute name="Main.Class" value="HelloProgram"/>

</manifest>

</jar>

</target>

</project>

build.xml的基本結構也是目標(target)、依賴(depends),以及實現目標的任務。比如在上面的腳本中,jar目標用來創建應用程序jar文件,該目標依賴於compile目標,後者執行的任務是創建一個名爲classes的文件夾,編譯當前目錄的java文件至classes目錄。compile目標完成後,jar目標再執行自己的任務。Ant有大量內置的用Java實現的任務,這保證了其跨平臺的特質,同時,Ant也有特殊的任務exec來執行本地命令。

和Make一樣,Ant也都是過程式的,開發者顯式地指定每一個目標,以及完成該目標所需要執行的任務。針對每一個項目,開發者都需要重新編寫這一過程,這裏其實隱含着很大的重複。Maven是聲明式的,項目構建過程和過程各個階段所需的工作都由插件實現,並且大部分插件都是現成的,開發者只需要聲明項目的基本元素,Maven就執行內置的、完整的構建過程。這在很大程度上消除了重複。

Ant是沒有依賴管理的,所以很長一段時間Ant用戶都不得不手工管理依賴,這是一個令人頭疼的問題。幸運的是,Ant用戶現在可以藉助Ivy管理依賴。而對於Maven用戶來說,依賴管理是理所當然的,Maven不僅內置了依賴管理,更有一個可能擁有全世界最多Java開源軟件包的中央倉庫,Maven用戶無須進行任何配置就可以直接享用。

1.2.5  不重複發明輪子

【該小節內容整理自網友Arthas最早在Maven中文MSN的羣內的討論,在此表示感謝】

小張是一家小型民營軟件公司的程序員,他所在的公司要開發一個新的Web項目。經過協商,決定使用Spring、iBatis和Tapstry。jar包去哪裏找呢?公司裏估計沒有人能把Spring、iBatis和Tapstry所使用的jar包一個不少地找出來。大家的做法是,先到Spring的站點上去找一個spring.with.dependencies,然後去iBatis的網站上把所有列出來的jar包下載下來,對Tapstry、Apache commons等執行同樣的操作。項目還沒有開始,WEB.INF/lib下已經有近百個jar包了,帶版本號的、不帶版本號的、有用的、沒用的、相沖突的,怎一個“亂”字了得!

在項目開發過程中,小張不時地發現版本錯誤和版本衝突問題,他只能硬着頭皮逐一解決。項目開發到一半,經理髮現最終部署的應用的體積實在太大了,要求小張去掉一些沒用的jar包,於是小張只能加班加點地一個個刪……

小張隱隱地覺得這些依賴需要一個框架或者系統來進行管理。

小張喜歡學習流行的技術,前幾年Ant十分流行,他學了,併成爲了公司這方面的專家。小張知道,Ant打包,無非就是創建目錄,複製文件,編譯源代碼,使用一堆任務,如copydir、fileset、classpath、ref、target,然後再jar、zip、war,打包就成功了。

項目經理髮話了:“兄弟們,新項目來了,小張,你來寫Ant腳本!”

“是,保證完成任務!”接着,小張繼續創建一個新的XML文件。target clean; target compile; target jar; …… 不知道他是否想過,在他寫的這麼多的Ant腳本中,有多少是重複勞動,有多少代碼會在一個又一個項目中重現。既然都差不多,有些甚至完全相同,爲什麼每次都要重新編寫?

終於有一天,小張意識到了這個問題,想複用Ant腳本,於是在開會時他說:“以後就都用我這個規範的Ant腳本吧,新的項目只要遵循我定義的目錄結構就可以了。”經理聽後覺得很有道理:“嗯,確實是個進步。”

這時新來的研究生髮言了:“經理,用Maven吧,這個在開源社區很流行,比Ant更方便。”小張一聽很驚訝,Maven真比自己的“規範化Ant”強大?其實他不知道自己只是在重新發明輪子,Maven已經有一大把現成的插件,全世界都在用,你自己不用寫任何代碼!

爲什麼沒有人說“我自己寫的代碼最靈活,所以我不用Spring,我自己實現IoC;我不用Hibernate,我自己封裝JDBC”?

1.3 Maven與極限編程 Top

極限編程(XP)是近些年在軟件行業紅得發紫的敏捷開發方法,它強調擁抱變化。該軟件開發方法的創始人Kent Beck提出了XP所追求的價值、實施原則和推薦實踐。下面看一下Maven是如何適應XP的。
首先看一下Maven如何幫助XP團隊實現一些核心價值:

  • 簡單。Maven暴露了一組一致、簡潔的操作接口,能幫助團隊成員從原來的高度自定義的、複雜的構建系統中解脫出來,使用Maven現有的成熟的、穩定的組件也能簡化構建系統的複雜度。
  • 交流與反饋。與版本控制系統結合後,所有人都能執行最新的構建並快速得到反饋。此外,自動生成的項目報告也能幫助成員瞭解項目的狀態,促進團隊的交流。

此外,Maven更能無縫地支持或者融入到一些主要的XP實踐中:

  • 測試驅動開發(TDD)。TDD強調測試先行,所有產品都應該由測試用例覆蓋。而測試是Maven生命週期的最重要的組成部分之一,並且Maven有現成的成熟插件支持業界流行的測試框架,如JUnit和TestNG。
  • 十分鐘構建。十分鐘構建強調我們能夠隨時快速地從源碼構建出最終的產品。這正是Maven所擅長的,只需要一些配置,之後用一條簡單的命令就能讓Maven幫你清理、編譯、測試、打包、部署,然後得到最終的產品。
  • 持續集成(CI)。CI強調項目以很短的週期(如15分鐘)集成最新的代碼。 實際上,CI的前提是源碼管理系統和構建系統。目前業界流行的CI服務器如Hudson和CruiseControl都能很好地和Maven進行集成。也 就是說,使用Maven後,持續集成會變得更加方便。
  • 富有信息的工作區。 這條實踐強調開發者能夠快速方便地瞭解到項目的最新狀態。當然,Maven並不會幫你把測試覆蓋率報告貼到牆上,也不會在你的工作臺上放個鴨子告訴你構建 失敗了。不過使用Maven發佈的項目報告站點,並配置你需要的項目報告,如測試覆蓋率報告,都能幫你把信息推送到開發者眼前。

上述這些實踐並非只在XP中適用。事實上,除了其他敏捷開發方法如SCRUM之外,幾乎任何軟件開發方法都能借鑑這些實踐。也就是說,Maven幾乎能夠很好地支持任何軟件開發方法。
例 如,在傳統的瀑布模型開發中,項目依次要經歷需求開發、分析、設計、編碼、測試和集成發佈階段。從設計和編碼階段開始,就可以使用Maven來建立項目的 構建系統。在設計階段,也完全可以針對設計開發測試用例,然後再編寫代碼來滿足這些測試用例。然而,有了自動化構建系統,我們可以節省很多手動的測試時 間。此外,儘早地使用構建系統集成團隊的代碼,對項目也是百利而無一害。最後,Maven還能幫助我們快速地發佈項目。

第2章 Maven的安裝和配置 Top

第1章介紹了Maven是什麼,以及爲什麼要使用Maven, 我們將從本章實際開始實際接觸Maven。本章首先將介紹如何在主流的操作系統下安裝Maven,並詳細解釋Maven的安裝文件;其次還會介紹如何在主 流的IDE中集成Maven,以及Maven安裝的最佳實踐。
2.1 在Windows上安裝Maven
2.2 在基於Unix的系統上安裝Maven
2.3 安裝目錄分析
2.4 設置HTTP代理
2.5 安裝m2eclipse
2.6 安裝NetBeans Maven插件
2.7 Maven安裝最佳實踐
2.8 小結

2.1 在Windows上安裝Maven Top

2.1.1 檢查JDK安裝

在安裝Maven之前,首先要確認你已經正確安裝了JDK。Maven可以運行在JDK 1.4及以上的版本上。本書的所有樣例都基於JDK 5及以上版本。打開Windows的命令行,運行如下的命令來檢查你的Java安裝:

C:\Users\Juven Xu>echo %JAVA_HOME%

C:\Users\Juven Xu>java -version

結果如圖2-1所示:



 圖2-1 Windows中檢查Java安裝

上述命令首先檢查環境變量JAVA_HOME是否指向了正確的JDK目錄,接着嘗試運行java命令。如果Windows無法執行java命令,或者無法找到JAVA_HOME環境變量。你就需要檢查Java是否安裝了,或者環境變量是否設置正確。關於環境變量的設置,請參考2.1.3節。

2.1.2 下載Maven

請訪問Maven的下載頁面:http://maven.apache.org/download.html,其中包含針對不同平臺的各種版本的Maven下載文件。對於首次接觸Maven的讀者來說,推薦使用Maven 3.0,,因此下載apache-maven-3.0-bin.zip。當然,如果你對Maven的源代碼感興趣並想自己構建Maven,還可以下載apache-maven-3.0 -src.zip。該下載頁面還提供了md5校驗和(checksum)文件和asc數字簽名文件,可以用來檢驗Maven分發包的正確性和安全性。

在本書編寫的時候,Maven 2的最新版本是2.2.1,Maven 3基本完全兼容Maven 2,而且較之於Maven 2它性能更好,還有不少功能的改進,如果你之前一直使用Maven 2,現在正猶豫是否要升級,那就大可不必擔心了,快點嘗試下Maven 3吧! 

2.1.3 本地安裝

將安裝文件解壓到你指定的目錄中,如:

D:\bin>jar xvf "C:\Users\Juven Xu\Downloads\apache-maven-3.0--bin.zip"

這裏的Maven安裝目錄是D:\bin\apache-maven-3.0,接着需要設置環境變量,將Maven安裝配置到操作系統環境中。

打開系統屬性面板(桌面上右鍵單擊“我的電腦”→“屬性”),點擊高級系統設置,再點擊環境變量,在系統變量中新建一個變量,變量名爲M2_HOME,變量值爲Maven的安裝目錄D:\bin\apache-maven-3.0。點擊確定,接着在系統變量中找到一個名爲Path的變量,在變量值的末尾加上%M2_HOME%\bin;,注意多個值之間需要有分號隔開,然後點擊確定。至此,環境變量設置完成,詳細情況如圖2-2所示:

圖2-2 Windows中系統環境變量配置

這裏需要提一下的是Path環境變量,當我們在cmd中輸入命令時,Windows首先會在當前目錄中尋找可執行文件或腳本,如果沒有找到,Windows會接着遍歷環境變量Path中定義的路徑。由於我們將%M2_HOME%\bin添加到了Path中,而這裏%M2_HOME%實際上是引用了我們前面定義的另一個變量,其值是Maven的安裝目錄。因此,Windows會在執行命令時搜索目錄D:\bin\apache-maven-3.0\bin,而mvn執行腳本的位置就是這裏。

明白了環境變量的作用,現在打開一個新的cmd窗口(這裏強調新的窗口是因爲新的環境變量配置需要新的cmd窗口才能生效),運行如下命令檢查Maven的安裝情況:

C:\Users\Juven Xu>echo %M2_HOME%

C:\Users\Juven Xu>mvn -v

運行結果如圖2-3所示:


 圖2-3 Windows中檢查Maven安裝

第一條命令echo %M2_HOME%用來檢查環境變量M2_HOME是否指向了正確的Maven安裝目錄;而mvn –version執行了第一條Maven命令,以檢查Windows是否能夠找到正確的mvn執行腳本。

2.1.4 升級Maven

Maven還比較年輕,更新比較頻繁,因此用戶往往會需要更新Maven安裝以獲得更多更酷的新特性,以及避免一些舊的bug。

在Windows上更新Maven非常簡便,只需要下載新的Maven安裝文件,解壓至本地目錄,然後更新M2_HOME環境變量便可。例如,假設Maven推出了新版本3.1,我們將其下載然後解壓至目錄D:\bin\apache-maven-3.1,接着遵照前一節描述的步驟編輯環境變量M2_HOME,更改其值爲D:\bin\apache-maven-3.1。至此,更新就完成了。同理,如果你需要使用某一箇舊版本的Maven,也只需要編輯M2_HOME環境變量指向舊版本的安裝目錄。

2.2 在基於Unix的系統上安裝Maven Top

Maven是跨平臺的,它可以在任何一種主流的操作系統上運行,本節將介紹如何在基於Unix的系統(包括Linux、Mac OS以及FreeBSD等)上安裝Maven。

2.2.1 下載和安裝

首先,與在Windows上安裝Maven一樣,需要檢查JAVA_HOME環境變量以及Java命令,細節不再贅述,命令如下:

juven@juven-ubuntu:~$ echo $JAVA_HOME

juven@juven-ubuntu:~$ java –version

運行結果如圖2-4所示:

圖2-4 Linux中檢查Java安裝

接着到http://maven.apache.org/download.html下載Maven安裝文件,如apache-maven-3.0-bin.tar.gz,然後解壓到本地目錄:

juven@juven-ubuntu:bin$ tar -xvzf apache-maven-3.0-bin.tar.gz

現在已經創建好了一個Maven安裝目錄apache-maven-3.0,雖然直接使用該目錄配置環境變量之後就能使用Maven了,但這裏我更推薦做法是,在安裝目錄旁平行地創建一個符號鏈接,以方便日後的升級:

juven@juven-ubuntu:bin$ ln -s apache-maven-3.0 apache-maven
juven@juven-ubuntu:bin$ ls -l
total 4
lrwxrwxrwx 1 juven juven   18 2009-09-20 15:43 apache-maven -> apache-maven-3.0
drwxr-xr-x 6 juven juven 4096 2009-09-20 15:39 apache-maven-3.0

接下來,我們需要設置M2_HOME環境變量指向符號鏈接apache-maven-,並且把Maven安裝目錄下的bin/文件夾添加到系統環境變量PATH中去:

juven@juven-ubuntu:bin$ export M2_HOME=/home/juven/bin/apache-maven
juven@juven-ubuntu:bin$ export PATH=$PATH:$M2_HOME/bin

一般來說,需要將這兩行命令加入到系統的登錄shell腳本中去,以我現在的Ubuntu 8.10爲例,編輯~/.bashrc文件,添加這兩行命令。這樣,每次啓動一個終端,這些配置就能自動執行。

至此,安裝完成,我們可以運行以下命令檢查Maven安裝:

juven@juven-ubuntu:bin$ echo $M2_HOME

juven@juven-ubuntu:bin$ mvn –version

運行結果如圖2-5所示:

 圖2-5 Linux中檢查Maven安裝

2.2.2 升級Maven

在基於Unix的系統上,可以利用符號鏈接這一工具來簡化Maven的升級,不必像在Windows上那樣,每次升級都必須更新環境變量。

前一小節中我們提到,解壓Maven安裝包到本地之後,平行地創建一個符號鏈接,然後在配置環境變量時引用該符號鏈接,這樣做是爲了方便升級。現在,假設我們需要升級到新的Maven 3.1版本,同理,將安裝包解壓到與前一版本平行的目錄下,然後更新符號鏈接指向3.1版的目錄便可:

juven@juven-ubuntu:bin$ rm apache-maven
juven@juven-ubuntu:bin$ ln -s apache-maven-3.1/ apache-maven
juven@juven-ubuntu:bin$ ls -l
total 8
lrwxrwxrwx 1 juven juven   17 2009-09-20 16:13 apache-maven -> apache-maven-3.1 /
drwxr-xr-x 6 juven juven 4096 2009-09-20 15:39 apache-maven-3.0drwxr-xr-x 2 juven juven 4096 2009-09-20 16:09 apache-maven-3.1

同理,可以很方便地切換到Maven的任意一個版本。現在升級完成了,可以運行mvn -v進行檢查。

2.3 安裝目錄分析 Top

本章前面的內容講述瞭如何在各種操作系統中安裝和升級Maven。現在我們來仔細分析一下Maven的安裝文件。

2.3.1 M2_HOME

前面我們講到設置M2_HOME環境變量指向Maven的安裝目錄,本書之後所有使用M2_HOME的地方都指代了該安裝目錄,讓我們看一下該目錄的結構和內容:

bin
boot
conf
lib
LICENSE.txt
NOTICE.txt
README.txt

  •  Bin: 該目錄包含了mvn運行的腳本,這些腳本用來配置Java命令,準備好classpath和相關的Java系統屬性,然後執行Java命令。其中mvn是基於UNIX平臺的shell腳本,mvn.bat是基於Windows平臺的bat腳本。在命令行輸入任何一條mvn命令時,實際上就是在調用這些腳本。該目錄還包含了mvnDebugmvnDebug.bat兩個文件,同樣,前者是UNIX平臺的shell腳本,後者是windows的bat腳本。那麼mvn和mvnDebug有什麼區別和關係呢?打開文件我們就可以看到,兩者基本是一樣的,只是mvnDebug多了一條MAVEN_DEBUG_OPTS配置,作用就是在運行Maven時開啓debug,以便調試Maven本身。此外,該目錄還包含m2.conf文件,這是classworlds的配置文件,稍微會介紹classworlds。
  • Boot: 該目錄只包含一個文件,以maven 3.0爲例,該文件爲plexus-classworlds-2.2.3.jar。plexus-classworlds是一個類加載器框架,相對於默認的java類加載器,它提供了更豐富的語法以方便配置,Maven使用該框架加載自己的類庫。更多關於classworlds的信息請參考http://classworlds.codehaus.org/。對於一般的Maven用戶來說,不必關心該文件。
  • Conf: 該目錄包含了一個非常重要的文件settings.xml。直接修改該文件,就能在機器上全局地定製Maven的行爲。一般情況下,我們更偏向於複製該文件至~/.m2/目錄下(這裏~表示用戶目錄),然後修改該文件,在用戶範圍定製Maven的行爲。本書的後面將會多次提到該settings.xml,並逐步分析其中的各個元素。 
  • Lib: 該目錄包含了所有Maven運行時需要的Java類庫,Maven本身是分模塊開發的,因此用戶能看到諸如mavn-core-3.0.jar、maven-model-3.0.jar之類的文件,此外這裏還包含一些Maven用到的第三方依賴如common-cli-1.2.jar、google-collection-1.0.jar等等。(對於Maven 2來說,該目錄只包含一個如maven-2.2.1-uber.jar的文件原本各爲獨立JAR文件的Maven模塊和第三方類庫都被拆解後重新合併到了這個JAR文件中)。可以說,這個lib目錄就是真正的Maven。關於該文件,還有一點值得一提的是,用戶可以在這個目錄中找到Maven內置的超級POM,這一點在8.5小節詳細解釋。其他:LICENSE.txt記錄了Maven使用的軟件許可證Apache License Version 2.0; NOTICE.txt記錄了Maven包含的第三方軟件;而README.txt則包含了Maven的簡要介紹,包括安裝需求及如何安裝的簡要指令等等。 

 

2.3.2 ~/.m2

在講述該小節之前,我們先運行一條簡單的命令:mvn help:system。該命令會打印出所有的Java系統屬性和環境變量,這些信息對我們日常的編程工作很有幫助。這裏暫不解釋help:system涉及的語法,運行這條命令的目的是爲了讓Maven執行一個真正的任務。我們可以從命令行輸出看到Maven會下載maven-help-plugin,包括pom文件和jar文件。這些文件都被下載到了Maven本地倉庫中。

現在打開用戶目錄,比如當前的用戶目錄是C:\Users\Juven Xu\,你可以在Vista和Windows7中找到類似的用戶目錄。如果是更早版本的Windows,該目錄應該類似於C:\Document and Settings\Juven Xu\。在基於Unix的系統上,直接輸入cd 回車,就可以轉到用戶目錄。爲了方便,本書統一使用符號 指代用戶目錄。

在用戶目錄下,我們可以發現.m2文件夾。默認情況下,該文件夾下放置了Maven本地倉庫.m2/repository。所有的Maven構件(artifact)都被存儲到該倉庫中,以方便重用。我們可以到~/.m2/repository/org/apache/maven/plugins/maven-help-plugins/目錄下找到剛纔下載的maven-help-plugin的pom文件和jar文件。Maven根據一套規則來確定任何一個構件在倉庫中的位置,這一點本書第6章將會詳細闡述。由於Maven倉庫是通過簡單文件系統透明地展示給Maven用戶的,有些時候可以繞過Maven直接查看或修改倉庫文件,在遇到疑難問題時,這往往十分有用。

默認情況下,~/.m2目錄下除了repository倉庫之外就沒有其他目錄和文件了,不過大多數Maven用戶需要複製M2_HOME/conf/settings.xml文件到~/.m2/settings.xml。這是一條最佳實踐,我們將在本章最後一小節詳細解釋。

2.4 設置HTTP代理 Top

有時候你所在的公司由於安全因素考慮,要求你使用通過安全認證的代理訪問因特網。這種情況下,就需要爲Maven配置HTTP代理,才能讓它正常訪問外部倉庫,以下載所需要的資源。

首先確認自己無法直接訪問公共的Maven中央倉庫,直接運行命令ping repo1.maven.org可以檢查網絡。如果真的需要代理,先檢查一下代理服務器是否暢通,比如現在有一個IP地址爲218.14.227.197,端口爲3128的代理服務,我們可以運行telnet 218.14.227.197 3128來檢測該地址的該端口是否暢通。如果得到出錯信息,需要先獲取正確的代理服務信息;如果telnet連接正確,則輸入ctrl+],然後q,回車,退出即可。

檢查完畢之後,編輯~/.m2/settings.xml文件(如果沒有該文件,則複製$M2_HOME/conf/settings.xml)。添加代理配置如下:

<settings>
…  
<proxies>

    <proxy>

      <id>my-proxy</id>

      <active>true</active>

      <protocol>http</protocol>

      <host>218.14.227.197</host>

      <port>3128</port>

      <!--

      <username>***</username>

      <password>***</password>

      <nonProxyHosts>repository.mycom.com|*.google.com</nonProxyHosts>

      -->

    </proxy>

  </proxies>
  …
</settings>

這段配置十分簡單,proxies下可以有多個proxy元素,如果你聲明瞭多個proxy元素,則默認情況下第一個被激活的proxy會生效。這裏聲明瞭一個id爲my-proxy的代理,active的值爲true表示激活該代理,protocol表示使用的代理協議,這裏是http。當然,最重要的是指定正確的主機名(host元素)和端口(port元素)。上述XML配置中我註釋掉了username、password、nonProxyHost幾個元素,當你的代理服務需要認證時,就需要配置username和password。nonProxyHost元素用來指定哪些主機名不需要代理,可以使用 | 符號來分隔多個主機名。此外,該配置也支持通配符,如*.google.com表示所有以google.com結尾的域名訪問都不要通過代理。

2.5 安裝m2eclipse Top

Eclipse是一款非常優秀的IDE。除了基本的語法標亮、代碼補齊、XML編輯等基本功能外,最新版的Eclipse還能很好地支持重構,並且集成了JUnit、CVS、Mylyn等各種流行工具。可惜Eclipse默認沒有集成對Maven的支持。幸運的是,由Maven之父Jason Van Zyl創立的Sonatype公司建立了m2eclipse項目,這是Eclipse下的一款十分強大的Maven插件,可以訪問http://m2eclipse.sonatype.org/ 瞭解更多該項目的信息。

本小節將先介紹如何安裝m2eclipse插件,本書後續的章節會逐步介紹m2eclipse插件的使用。

現在我以Eclipse 3.6爲例逐步講解m2eclipse的安裝。啓動Eclipse之後,在菜單欄中選擇Help,然後選擇Install New Software…,接着你會看到一個Install對話框,點擊Work with:字段邊上的Add按鈕,你會得到一個新的Add Repository對話框,在Name字段中輸入m2e,Location字段中輸入http://m2eclipse.sonatype.org/sites/m2e,然後點擊OK。Eclipse會下載m2eclipse安裝站點上的資源信息。等待資源載入完成之後,我們再將其全部展開,就能看到圖2-6所示的界面:



 圖2-6  m2eclipse的核心安裝資源列表

 

如圖顯示了m2eclipse的核心模塊Maven Integration for Eclipse (Required),選擇後點擊Next >,Eclipse會自動計算模塊間依賴,然後給出一個將被安裝的模塊列表,確認無誤後,繼續點擊Next >,這時我們會看到許可證信息,m2eclipse使用的開源許可證是Eclipse Public License v1.0,選擇I accept the terms of the license agreements,然後點擊Finish,接着就耐心等待Eclipse下載安裝這些模塊,如圖2-7所示:



 圖2-7:m2eclipse安裝進度

除了核心組件之外,m2eclipse還提供了一組額外組件,主要是爲了方便與其它工具如Subversion進行集成,這些組件的安裝地址爲http://m2eclipse.sonatype.org/sites/m2e-extras。使用前面類似的安裝方法,我們可以看到如圖2-8的組件列表:



 圖2-8:m2eclipse的額外組件安裝資源列表

下面簡單解釋一下這些組件的用途:

1. 重要的

  •  Maven SCM handler for Subclipse  (Optional):Subversion是非常流行的版本管理工具,該模塊能夠幫助我們直接從Subversion服務器簽出Maven項目,不過前提是需要首先安裝Subclipse(http://subclipse.tigris.org/)。
  •  Maven SCM Integration (Optional):Eclipse環境中Maven與SCM集成核心的模塊,它利用各種SCM工具如SVN實現Maven項目的簽出和具體化等操作。

2. 不重要的

  •  Maven issue tracking configurator for Mylyn 3.x (Optional):該模塊能夠幫助我們使用POM中的缺陷跟蹤系統信息連接Mylyn至服務器。
  •  Maven SCM handler for Team/CVS (Optional):該模塊幫助我們從CVS服務器簽出Maven項目,如果你還在使用CVS,就需要安裝它。
  •  Maven Integration for WTP (Optional):使用該模塊可以讓Eclipse自動讀取POM信息並配置WTP項目。、
  •  M2eclipse Extensions Development Support (Optional):用來支持擴展m2eclipse,一般用戶不會用到。
  •  Project configurators for commonly used maven plugins (temporary):一個臨時的組件,用來支持一些Maven插件與Eclipse的集成,建議安裝。

讀者可以根據自己的需要安裝相應組件,具體步驟不再贅述。

待安裝完畢後,重啓Eclipse,現在讓我們驗證一下m2eclipse是否正確安裝了。首先,點擊菜單欄中的Help,然後選擇About Eclipse,在彈出的對話框中,點擊Installation Details按鈕,會得到一個對話框,在Installed Software標籤欄中,檢查剛纔我們選擇的模塊是否在這個列表中,如圖2-9所示:



 圖2-9m2eclipse安裝結果

如果一切沒問題,我們再檢查一下Eclipse現在是否已經支持創建Maven項目,依次點擊菜單欄中的FileNewOther,在彈出的對話框中,找到Maven一項,再將其展開,你應該能夠看到如圖2-10所示的對話框:



 圖2-10 Eclipse中創建Maven項目嚮導

如果一切正常,說明m2eclipse已經正確安裝了。

最後,關於m2eclipse的安裝,需要提醒的一點是,你可能會在使用m2eclipse時遇到類似這樣的錯誤:

09-10-6 上午01時14分49秒: Eclipse is running in a JRE, but a JDK is required
Some Maven plugins may not work when importing projects or updating source folders.

這是因爲Eclipse默認是運行在JRE上的,而m2eclipse的一些功能要求使用JDK,解決方法是配置Eclipse安裝目錄的eclipse.ini文件,添加vm配置指向JDK,如:

--launcher.XXMaxPermSize

256m

-vm

D:\java\jdk1.6.0_07\bin\javaw.exe

-vmargs

-Dosgi.requiredJavaVersion=1.5

-Xms128m

-Xmx256m

2.6 安裝NetBeans Maven插件 Top

本小節會先介紹如何在NetBeans上安裝Maven插件,後面的章節中還會介紹NetBeans中具體的Maven操作。

首先,如果你正在使用NetBeans 6.7及以上版本,那麼Maven插件已經預裝了。你可以檢查Maven插件安裝,點擊菜單欄中的工具,接着選擇插件,在彈出的插件對話框中選擇已安裝標籤,你應該能夠看到Maven插件,如圖2-11所示:



 圖2-11 已安裝的NetBeans Maven插件

如果你在使用NetBeans 6.7之前的版本,或者由於某些原因NetBeans Maven插件被卸載了,那麼你就需要安裝NetBeans Maven插件,下面我們以NetBeans 6.1爲例,介紹Maven插件的安裝。

同樣,點擊菜單欄中的工具,選擇插件,在彈出的插件對話框中選擇可用插件標籤,接着在右邊的搜索框內輸入Maven,這時你會在左邊的列表中看到一個名爲Maven的插件,選擇該插件,然後點擊下面的安裝按鈕,如圖2-12所示:

圖2-12 安裝NetBeans Maven插件

接着在隨後的對話框中根據提示操作,閱讀相關許可證並接受,NetBeans會自動幫我們下載並安裝Maven插件,結束之後會提示安裝完成,之後再點擊插件對話框的已安裝標籤,就能看到已經激活的Maven插件。

最後,爲了確認Maven插件確實已經正確安裝了,可以看一下NetBeans是否已經擁有創建Maven項目的相關菜單。在菜單欄中選擇文件,然後選擇新建項目,這時應該能夠看到項目類別中有Maven一項,選擇該類別,右邊會相應地顯示Maven項目基於現有POM的Maven項目,如圖2-13所示:


 圖2-13 NetBeans中創建Maven項目嚮導

如果你能看到類似的對話框,說明NetBeans Maven已經正確安裝了。

2.7 Maven安裝最佳實踐 Top

本節介紹一些在安裝Maven過程中不是必須的,但十分有用的實踐。

2.7.1 設置MAVEN_OPTS環境變量

本章前面介紹Maven安裝目錄時我們瞭解到,運行mvn命令實際上是執行了Java命令,既然是運行Java,那麼運行Java命令可用的參數當然也應該在運行mvn命令時可用。這個時候,MAVEN_OPTS環境變量就能派上用場。

我們通常需要設置MAVEN_OPTS的值爲:-Xms128m -Xmx512m,因爲Java默認的最大可用內存往往不能夠滿足Maven運行的需要,比如在項目較大時,使用Maven生成項目站點需要佔用大量的內存,如果沒有該配置,我們很容易得到java.lang.OutOfMemeoryError。因此,一開始就配置該變量是推薦的做法。

關於如何設置環境變量,請參考前面設置M2_HOME環境變量的做法,儘量不要直接修改mvn.bat或者mvn這兩個Maven執行腳本文件。因爲如果修改了腳本文件,升級Maven時你就不得不再次修改,一來麻煩,二來容易忘記。同理,我們應該儘可能地不去修改任何Maven安裝目錄下的文件。

2.7.2 配置用戶範圍settings.xml

Maven用戶可以選擇配置$M2_HOME/conf/settings.xml或者~/.m2/settings.xml。前者是全局範圍的,整臺機器上的所有用戶都會直接受到該配置的影響,而後者是用戶範圍的,只有當前用戶纔會受到該配置的影響。

我們推薦使用用戶範圍的settings.xml,主要原因是爲了避免無意識地影響到系統中的其他用戶。當然,如果你有切實的需求,需要統一系統中所有用戶的settings.xml配置,當然應該使用全局範圍的settings.xml。

除了影響範圍這一因素,配置用戶範圍settings.xml文件還便於Maven升級。直接修改conf目錄下的settings.xml會導致Maven升級不便,每次升級到新版本的Maven,都需要複製settings.xml文件,如果使用~/.m2目錄下的settings.xml,就不會影響到Maven安裝文件,升級時就不需要觸動settings.xml文件。

2.7.3 不要使用IDE內嵌的Maven

無論是Eclipse還是NetBeans,當我們集成Maven時,都會安裝上一個內嵌的Maven,這個內嵌的Maven通常會比較新,但不一定很穩定,而且往往也會和我們在命令行使用的Maven不是同一個版本。這裏有會出現兩個潛在的問題:首先,較新版本的Maven存在很多不穩定因素,容易造成一些難以理解的問題;其次,除了IDE,我們也經常還會使用命令行的Maven,如果版本不一致,容易造成構建行爲的不一致,這是我們所不希望看到的。因此,我們應該在IDE中配置Maven插件時使用與命令行一致的Maven。

在m2eclipse環境中,點擊菜單欄中的Windows,然後選擇Preferences,在彈出的對話框中,展開左邊的Maven項,選擇Installation子項,在右邊的面板中,我們能夠看到有一個默認的Embedded Maven安裝被選中了,點擊Add…然後選擇我們的Maven安裝目錄M2_HOME,添加完畢之後選擇這一個外部的Maven,如圖2-14所示:



 圖2-14 在Eclipse中使用外部Maven

NetBeans Maven插件默認會偵測PATH環境變量,因此會直接使用與命令行一致的Maven環境。依次點擊菜單欄中的工具選項其他Maven標籤欄,你就能看到如圖2-15所示的配置:



 圖2-15 在NetBeans中使用外部Maven

2.8 小結 Top

本章詳細介紹了在各種操作系統平臺上安裝Maven,並對Maven安裝目錄進行了深入的分析,在命令行的基礎上,本章又進一步介紹了Maven與主流IDE Eclipse及NetBeans的集成,本章最後還介紹了一些與Maven安裝相關的最佳實踐。本書下一章會創建一個Hello World項目,帶領讀者配置和構建Maven項目。

第3章 Maven使用入門 Top

到目前爲止,我們已經大概瞭解並安裝好了Maven,現在,我們開始 創建一個最簡單的Hello World項目。如果你是初次接觸Maven,我建議你按照本章的內容一步步地編寫代碼並執行,可能你會碰到一些概念暫時難以理解,不用着急,記下這些疑 難點,相信本書的後續章節會幫你逐一解答。 
3.1 編寫POM 
3.2 編寫主代碼 
3.3 編寫測試代碼 
3.4 打包和運行 
3.5 使用Archetype生成項目骨架 
3.6 m2eclipse簡單使用 
3.7 NetBeans Maven插件簡單使用 
3.8 小結

3.1 編寫POM Top

就像Make的Makefile,Ant的build.xml一樣,Maven項目的核心是pom.xml。POM(Project Object Model,項目對象模型)定義了項目的基本信息,用於描述項目如何構建,聲明項目依賴,等等。現在我們先爲Hello World項目編寫一個最簡單的pom.xml。

首先創建一個名爲hello-world的文件夾(本書中各章的代碼都會對應一個以ch開頭的項目),打開該文件夾,新建一個名爲pom.xml的文件,輸入其內容如代碼清單3-1:

代碼清單3-1:Hello World的POM

  1. <span style="font-size: small;"><?xml version="1.0" encoding="UTF-8"?>  
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"  
  3.          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0  
  5. http://maven.apache.org/maven-v4_0_0.xsd">  
  6.   <modelVersion>4.0.0</modelVersion>  
  7.   <groupId>com.juvenxu.mvnbook</groupId>  
  8.   <artifactId>hello-world</artifactId>  
  9.   <version>1.0-SNAPSHOT</version>  
  10.   <name>Maven Hello World Project</name>  
  11. </project>   
  12. </span>  

     代碼的第一行是XML頭,指定了該xml文檔的版本和編碼方式。緊接着是project元素,project是所有pom.xml的根元素,它還聲明瞭一些POM相關的命名空間及xsd元素,雖然這些屬性不是必須的,但使用這些屬性能夠讓第三方工具(如IDE中的XML編輯器)幫助我們快速編輯POM。

根元素下的第一個子元素modelVersion指定了當前POM模型的版本,對於Maven2及Maven 3來說,它只能是4.0.0。

這段代碼中最重要的是groupId,artifactId和version三行。這三個元素定義了一個項目基本的座標,在Maven的世界,任何的jar、pom或者war都是以基於這些基本的座標進行區分的。

groupId定義了項目屬於哪個組,這個組往往和項目所在的組織或公司存在關聯,譬如你在googlecode上建立了一個名爲myapp的項目,那麼groupId就應該是com.googlecode.myapp,如果你的公司是mycom,有一個項目爲myapp,那麼groupId就應該是com.mycom.myapp。本書中所有的代碼都基於groupId com.juvenxu.mvnbook。

artifactId定義了當前Maven項目在組中唯一的ID,我們爲這個Hello World項目定義artifactId爲hello-world,本書其他章節代碼會被分配其他的artifactId。而在前面的groupId爲com.googlecode.myapp的例子中,你可能會爲不同的子項目(模塊)分配artifactId,如:myapp-util、myapp-domain、myapp-web等等。

顧名思義,version指定了Hello World項目當前的版本——1.0-SNAPSHOT。SNAPSHOT意爲快照,說明該項目還處於開發中,是不穩定的版本。隨着項目的發展,version會不斷更新,如升級爲1.0、1.1-SNAPSHOT、1.1、2.0等等。本書的6.5小節會詳細介紹SNAPSHOT,第13章介紹如何使用Maven管理項目版本的升級發佈。

最後一個name元素聲明瞭一個對於用戶更爲友好的項目名稱,雖然這不是必須的,但我還是推薦爲每個POM聲明name,以方便信息交流。

沒有任何實際的Java代碼,我們就能夠定義一個Maven項目的POM,這體現了Maven的一大優點,它能讓項目對象模型最大程度地與實際代碼相獨立,我們可以稱之爲解耦,或者正交性,這在很大程度上避免了Java代碼和POM代碼的相互影響。比如當項目需要升級版本時,只需要修改POM,而不需要更改Java代碼;而在POM穩定之後,日常的Java代碼開發工作基本不涉及POM的修改。

3.2 編寫主代碼 Top

項目主代碼和測試代碼不同,項目的主代碼會被打包到最終的構件中(比如jar),而測試代碼只在運行測試時用到,不會被打包。默認情況下,Maven假設項目主代碼位於src/main/java目錄,我們遵循Maven的約定,創建該目錄,然後在該目錄下創建文件com/juvenxu/mvnbook/helloworld/HelloWorld.java,其內容如代碼清單3-2:

代碼清單3-2:Hello World的主代碼

  1. <span style="font-size: small;">package com.juvenxu.mvnbook.helloworld;  
  2.    
  3. public class HelloWorld  
  4. {  
  5.    public String sayHello()  
  6.    {  
  7.      return "Hello Maven";  
  8.    }  
  9.   
  10.   public static void main(String[] args)  
  11.    {  
  12.      System.out.print( new HelloWorld().sayHello() );  
  13.    }  
  14. }  
  15. </span>  

       這是一個簡單的Java類,它有一個sayHello()方法,返回一個String。同時這個類還帶有一個main方法,創建一個HelloWorld實例,調用sayHello()方法,並將結果輸出到控制檯。

關於該Java代碼有兩點需要注意。首先,在95%以上的情況下,我們應該把項目主代碼放到src/main/java/目錄下(遵循Maven的約定),而無須額外的配置,Maven會自動搜尋該目錄找到項目主代碼。其次,該Java類的包名是com.juvenxu.mvnbook.helloworld,這與我們之前在POM中定義的groupId和artifactId相吻合。一般來說,項目中Java類的包都應該基於項目的groupId和artifactId,這樣更加清晰,更加符合邏輯,也方便搜索構件或者Java類。

代碼編寫完畢後,我們使用Maven進行編譯,在項目根目錄下運行命令 mvn clean compile ,我們會得到如下輸出:


  1. <span style="font-size: small;">[INFO] Scanning for projects...  
  2. [INFO] ------------------------------------------------------------------------  
  3. [INFO] Building Maven Hello World Project  
  4. [INFO]    task-segment: [clean, compile]  
  5. [INFO] ------------------------------------------------------------------------  
  6. [INFO] [clean:clean {execution: default-clean}]  
  7. [INFO] Deleting directory D:\code\hello-world\target  
  8. [INFO] [resources:resources {execution: default-resources}]  
  9. [INFO] skip non existing resourceDirectory D: \code\hello-world\src\main\resources  
  10. [INFO] [compiler:compile {execution: default-compile}]  
  11. [INFO] Compiling 1 source file to D: \code\hello-world\target\classes  
  12. [INFO] ------------------------------------------------------------------------  
  13. [INFO] BUILD SUCCESSFUL  
  14. [INFO] ------------------------------------------------------------------------  
  15. [INFO] Total time: 1 second  
  16. [INFO] Finished at: Fri Oct 09 02:08:09 CST 2009  
  17. [INFO] Final Memory: 9M/16M  
  18. [INFO] ------------------------------------------------------------------------  
  19. </span>  

 

clean告訴Maven清理輸出目錄target/,compile告訴Maven編譯項目主代碼,從輸出中我們看到Maven首先執行了clean:clean任務,刪除target/目錄,默認情況下Maven構建的所有輸出都在target/目錄中;接着執行resources:resources任務(未定義項目資源,暫且略過);最後執行compiler:compile任務,將項目主代碼編譯至target/classes目錄(編譯好的類爲com/juvenxu/mvnbook/helloworld/HelloWorld.Class)。

上文提到的clean:clean、resources:resources,以及compiler:compile對應了一些Maven插件及插件目標,比如clean:clean是clean插件的clean目標,compiler:compile是compiler插件的compile目標,後文會詳細講述Maven插件及其編寫方法。

至此,Maven在沒有任何額外的配置的情況下就執行了項目的清理和編譯任務,接下來,我們編寫一些單元測試代碼並讓Maven執行自動化測試。

3.3 編寫測試代碼 Top

爲了使項目結構保持清晰,主代碼與測試代碼應該分別位於獨立的目錄中。3.2節講過Maven項目中默認的主代碼目錄是src/main/java,對應地,Maven項目中默認的測試代碼目錄是src/test/java。因此,在編寫測試用例之前,我們先創建該目錄。

在Java世界中,由Kent Beck和Erich Gamma建立的JUnit是事實上的單元測試標準。要使用JUnit,我們首先需要爲Hello World項目添加一個JUnit依賴,修改項目的POM如代碼清單3-3:

代碼清單3-3:爲Hello World的POM添加依賴

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"  
  3.          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0  
  5. http://maven.apache.org/maven-v4_0_0.xsd">  
  6.   <modelVersion>4.0.0</modelVersion>  
  7.   <groupId>com.juvenxu.mvnbook</groupId>  
  8.   <artifactId>hello-world</artifactId>  
  9.   <version>1.0-SNAPSHOT</version>  
  10.   <name>Maven Hello World Project</name>  
  11.   <dependencies>  
  12.     <dependency>  
  13.        <groupId>junit</groupId>  
  14.        <artifactId>junit</artifactId>  
  15.        <version>4.7</version>  
  16.        <scope>test</scope>  
  17.     </dependency>  
  18.   </dependencies>  
  19. </project>    

     代碼中添加了dependencies元素,該元素下可以包含多個dependency元素以聲明項目的依賴,這裏我們添加了一個依賴——groupId是junit,artifactId是junit,version是4.7。前面我們提到groupId、artifactId和version是任何一個Maven項目最基本的座標,JUnit也不例外,有了這段聲明,Maven就能夠自動下載junit-4.7.jar。也許你會問,Maven從哪裏下載這個jar呢?在Maven之前,我們可以去JUnit的官網下載分發包。而現在有了Maven,它會自動訪問中央倉庫(http://repo1.maven.org/maven2/),下載需要的文件。讀者也可以自己訪問該倉庫,打開路徑junit/junit/4.7/,就能看到junit-4.7.pom和junit-4.7.jar。本書第6章會詳細介紹Maven倉庫及中央倉庫。

上述POM代碼中還有一個值爲test的元素scope,scope爲依賴範圍,若依賴範圍爲test則表示該依賴只對測試有效,換句話說,測試代碼中的import JUnit代碼是沒有問題的,但是如果我們在主代碼中用import JUnit代碼,就會造成編譯錯誤。如果不聲明依賴範圍,那麼默認值就是compile,表示該依賴對主代碼和測試代碼都有效。

配置了測試依賴,接着就可以編寫測試類,回顧一下前面的HelloWorld類,現在我們要測試該類的sayHello()方法,檢查其返回值是否爲“Hello Maven”。在src/test/java目錄下創建文件,其內容如代碼清單3-4:

代碼清單3-4:Hello World的測試代碼

  1. package com.juvenxu.mvnbook.helloworld;  
  2. import static org.junit.Assert.assertEquals;  
  3. import org.junit.Test;  
  4.   
  5. public class HelloWorldTest  
  6. {  
  7.     @Test  
  8.     public void testSayHello()  
  9.     {  
  10.         HelloWorld helloWorld = new HelloWorld();  
  11.   
  12.         String result = helloWorld.sayHello();  
  13.   
  14.         assertEquals( "Hello Maven", result );  
  15.     }  
  16. }   

一個典型的單元測試包含三個步驟:一,準備測試類及數據;二,執行要測試的行爲;三,檢查結果。上述樣例中,我們首先初始化了一個要測試的HelloWorld實例,接着執行該實例的sayHello()方法並保存結果到result變量中,最後使用JUnit框架的Assert類檢查結果是否爲我們期望的”Hello Maven”。在JUnit 3中,約定所有需要執行測試的方法都以test開頭,這裏我們使用了JUnit 4,但我們仍然遵循這一約定,在JUnit 4中,需要執行的測試方法都應該以@Test進行標註。

測試用例編寫完畢之後就可以調用Maven執行測試,運行 mvn clean test :

  1. [INFO] Scanning for projects...  
  2. [INFO] ------------------------------------------------------------------------  
  3. [INFO] Building Maven Hello World Project  
  4. [INFO]    task-segment: [clean, test]  
  5. [INFO] ------------------------------------------------------------------------  
  6. [INFO] [clean:clean {execution: default-clean}]  
  7. [INFO] Deleting directory D:\git-juven\mvnbook\code\hello-world\target  
  8. [INFO] [resources:resources {execution: default-resources}]  
  9. …  
  10. Downloading: http://repo1.maven.org/maven2/junit/junit/4.7/junit-4.7.pom  
  11. 1K downloaded  (junit-4.7.pom)  
  12. [INFO] [compiler:compile {execution: default-compile}]  
  13. [INFO] Compiling 1 source file to D: \code\hello-world\target\classes  
  14. [INFO] [resources:testResources {execution: default-testResources}]  
  15. …  
  16. Downloading: http://repo1.maven.org/maven2/junit/junit/4.7/junit-4.7.jar  
  17. 226K downloaded  (junit-4.7.jar)  
  18. [INFO] [compiler:testCompile {execution: default-testCompile}]  
  19. [INFO] Compiling 1 source file to D:\ code\hello-world\target\test-classes  
  20. [INFO] ------------------------------------------------------------------------  
  21. [ERROR] BUILD FAILURE  
  22. [INFO] ------------------------------------------------------------------------  
  23. [INFO] Compilation failure  
  24. D:\code\hello-world\src\test\java\com\juvenxu\mvnbook\helloworld\HelloWorldTest.java:[8,5] -source 1.3 中不支持註釋  
  25. (請使用 -source 5 或更高版本以啓用註釋)  
  26.     @Test  
  27. [INFO] ------------------------------------------------------------------------  
  28. [INFO] For more information, run Maven with the -e switch  
  29.   …  
 

不幸的是構建失敗了,不過我們先耐心分析一下這段輸出(爲了本書的簡潔,一些不重要的信息我用省略號略去了)。命令行輸入的是mvn clean test,而Maven實際執行的可不止這兩個任務,還有clean:clean、resources:resources、compiler:compile、resources:testResources以及compiler:testCompile。暫時我們需要了解的是,在Maven執行測試(test)之前,它會先自動執行項目主資源處理,主代碼編譯,測試資源處理,測試代碼編譯等工作,這是Maven生命週期的一個特性,本書後續章節會詳細解釋Maven的生命週期。

從輸出中我們還看到:Maven從中央倉庫下載了junit-4.7.pom和junit-4.7.jar這兩個文件到本地倉庫(~/.m2/repository)中,供所有Maven項目使用。

構建在執行compiler:testCompile任務的時候失敗了,Maven輸出提示我們需要使用-source 5或更高版本以啓動註釋,也就是前面提到的JUnit 4的@Test註解。這是Maven初學者常常會遇到的一個問題。由於歷史原因,Maven的核心插件之一compiler插件默認只支持編譯Java 1.3,因此我們需要配置該插件使其支持Java 5,見代碼清單3-5:

代碼清單3-5:配置maven-compiler-plugin支持Java 5

  1. <project>  
  2. …  
  3.   <build>  
  4.     <plugins>  
  5.        <plugin>  
  6.          <groupId>org.apache.maven.plugins</groupId>  
  7.          <artifactId>maven-compiler-plugin</artifactId>  
  8.          <configuration>  
  9.            <source>1.5</source>  
  10.            <target>1.5</target>  
  11.          </configuration>  
  12.        </plugin>  
  13.     </plugins>  
  14.   </build>  
  15. …  
  16. </project>    

該POM省略了除插件配置以外的其他部分,我們暫且不去關心插件配置的細節,只需要知道compiler插件支持Java 5的編譯。現在再執行mvn clean test,輸出如下:

  1. …  
  2. [INFO] [compiler:testCompile {execution: default-testCompile}]  
  3. [INFO] Compiling 1 source file to D: \code\hello-world\target\test-classes  
  4. [INFO] [surefire:test {execution: default-test}]  
  5. [INFO] Surefire report directory: D:\code\hello-world\target\surefire-reports  
  6. -------------------------------------------------------  
  7.  T E S T S  
  8. -------------------------------------------------------  
  9. Running com.juvenxu.mvnbook.helloworld.HelloWorldTest  
  10. Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.055 sec  
  11. Results :  
  12. Tests run: 1, Failures: 0, Errors: 0, Skipped: 0  
  13. [INFO] ------------------------------------------------------------------------  
  14. [INFO] BUILD SUCCESSFUL  
  15. [INFO] ------------------------------------------------------------------------  
  16. …  

我們看到compiler:testCompile任務執行成功了,測試代碼通過編譯之後在target/test-classes下生成了二進制文件,緊接着surefire:test任務運行測試,surefire是Maven世界中負責執行測試的插件,這裏它運行測試用例HelloWorldTest,並且輸出測試報告,顯示一共運行了多少測試,失敗了多少,出錯了多少,跳過了多少。顯然,我們的測試通過了——BUILD SUCCESSFUL。

3.4 打包和運行 Top

將項目進行編譯、測試之後,下一個重要步驟就是打包(package)。Hello World的POM中沒有指定打包類型,使用默認打包類型jar,我們可以簡單地執行命令 mvn clean package 進行打包,可以看到如下輸出:

  1. …  
  2. Tests run: 1, Failures: 0, Errors: 0, Skipped: 0  
  3.   
  4. [INFO] [jar:jar {execution: default-jar}]  
  5. [INFO] Building jar: D:\code\hello-world\target\hello-world-1.0-SNAPSHOT.jar  
  6. [INFO]   
  7. --------------------------------------------------------------------  
  8. [INFO] BUILD SUCCESSFUL  
  9. …  
 

類似地,Maven會在打包之前執行編譯、測試等操作。這裏我們看到jar:jar任務負責打包,實際上就是jar插件的jar目標將項目主代碼打包成一個名爲hello-world-1.0-SNAPSHOT.jar的文件,該文件也位於target/輸出目錄中,它是根據artifact-version.jar規則進行命名的,如有需要,我們還可以使用finalName來自定義該文件的名稱,這裏暫且不展開,本書後面會詳細解釋。

至此,我們得到了項目的輸出,如果有需要的話,就可以複製這個jar文件到其他項目的Classpath中從而使用HelloWorld類。但是,如何才能讓其他的Maven項目直接引用這個jar呢?我們還需要一個安裝的步驟,執行mvn clean install

  1.    …  
  2.    [INFO] [jar:jar {execution: default-jar}]  
  3.    [INFO] Building jar: D: \code\hello-world\target\hello-world-1.0-SNAPSHOT.jar  
  4.    [INFO] [install:install {execution: default-install}]  
  5.    [INFO] Installing D:\code\hello-world\target\hello-world-1.0-SNAPSHOT.jar to C:\Users\juven\.m2\repository\com\juvenxu\mvnbook\hello-world\1.0-SNAPSHOT\hello-world-1.0-SNAPSHOT.jar  
  6.    [INFO]  
  7. ------------------------------------------------------------------------  
  8.    [INFO] BUILD SUCCESSFUL  
  9.    …  

在打包之後,我們又執行了安裝任務install:install,從輸出我們看到該任務將項目輸出的jar安裝到了Maven本地倉庫中,我們可以打開相應的文件夾看到Hello World項目的pom和jar。之前講述JUnit的POM及jar的下載的時候,我們說只有構件被下載到本地倉庫後,才能由所有Maven項目使用,這裏是同樣的道理,只有將Hello World的構件安裝到本地倉庫之後,其他Maven項目才能使用它。

我們已經將體驗了Maven最主要的命令:mvn clean compile、mvn clean test、mvn clean package、mvn clean install。執行test之前是會先執行compile的,執行package之前是會先執行test的,而類似地,install之前會執行package。我們可以在任何一個Maven項目中執行這些命令,而且我們已經清楚它們是用來做什麼的。

到目前爲止,我們還沒有運行Hello World項目,不要忘了HelloWorld類可是有一個main方法的。默認打包生成的jar是不能夠直接運行的,因爲帶有main方法的類信息不會添加到manifest中(我們可以打開jar文件中的META-INF/MANIFEST.MF文件,將無法看到Main-Class一行)。爲了生成可執行的jar文件,我們需要藉助maven-shade-plugin,配置該插件如下:

  1. <plugin>  
  2. <groupId>org.apache.maven.plugins</groupId>  
  3.   <artifactId>maven-shade-plugin</artifactId>  
  4.   <version>1.2.1</version>  
  5.   <executions>  
  6.     <execution>  
  7.       <phase>package</phase>  
  8.       <goals>  
  9.         <goal>shade</goal>  
  10.       </goals>  
  11.       <configuration>  
  12.         <transformers>  
  13.           <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">            <mainClass>com.juvenxu.mvnbook.helloworld.HelloWorld</mainClass>  
  14.          </transformer>  
  15.        </transformers>  
  16.      </configuration>  
  17.      </execution>  
  18.   </executions>  
  19. </plugin>  
 

plugin元素在POM中的相對位置應該在<project><build><plugins>下面。我們配置了mainClass爲com.juvenxu.mvnbook.helloworld.HelloWorld,項目在打包時會將該信息放到MANIFEST中。現在執行 mvn clean install ,待構建完成之後打開target/目錄,我們可以看到hello-world-1.0-SNAPSHOT.jaroriginal-hello-world-1.0-SNAPSHOT.jar,前者是帶有Main-Class信息的可運行jar,後者是原始的jar,打開hello-world-1.0-SNAPSHOT.jarMETA-INF/MANIFEST.MF,可以看到它包含這樣一行信息:

Main-Class: com.juvenxu.mvnbook.helloworld.HelloWorld

現在,我們在項目根目錄中執行該jar文件:

D: \code\hello-world>java -jar target\hello-world-1.0-SNAPSHOT.jar

Hello Maven

控制檯輸出爲Hello Maven,這正是我們所期望的。

本小節介紹了Hello World項目,側重點是Maven而非Java代碼本身,介紹了POM、Maven項目結構、以及如何編譯、測試、打包,等等。

3.5 使用Archetype生成項目骨架 Top

Hello World項目中有一些Maven的約定:在項目的根目錄中放置pom.xml,在src/main/java目錄中放置項目的主代碼,在src/test/java中放置項目的測試代碼。我之所以一步一步地展示這些步驟,是爲了能讓可能是Maven初學者的你得到最實際的感受。我們稱這些基本的目錄結構和pom.xml文件內容稱爲項目的骨架,當你第一次創建項目骨架的時候,你還會饒有興趣地去體會這些默認約定背後的思想,第二次,第三次,你也許還會滿意自己的熟練程度,但第四、第五次做同樣的事情,就會讓程序員惱火了,爲此Maven提供了Archetype以幫助我們快速勾勒出項目骨架。

還是以Hello World爲例,我們使用maven archetype來創建該項目的骨架,離開當前的Maven項目目錄。

如果是Maven 3,簡單的運行:

mvn archetype:generate

如果是Maven 2,最好運行如下命令:

mvn org.apache.maven.plugins:maven-archetype-plugin:2.0-alpha-5:generate

很多資料會讓你直接使用更爲簡單的 mvn archetype:generate 命令,但在Maven2中這是不安全的,因爲該命令沒有指定archetype插件的版本,於是Maven會自動去下載最新的版本,進而可能得到不穩定的SNAPSHOT版本,導致運行失敗。然而在Maven 3中,即使用戶沒有指定版本,Maven也只會解析最新的穩定版本,因此這是安全的,具體內容見7.7小節。

我們實際上是在運行插件maven-archetype-plugin,注意冒號的分隔,其格式爲 groupId:artifactId:version:goal ,org.apache.maven.plugins 是maven官方插件的groupId,maven-archetype-plugin是archetype插件的artifactId,2.0-alpha-5 是目前該插件最新的穩定版,generate是我們要使用的插件目標。

緊接着我們會看到一段長長的輸出,有很多可用的archetype供我們選擇,包括著名的Appfuse項目的archetype,JPA項目的archetype等等。每一個archetype前面都會對應有一個編號,同時命令行會提示一個默認的編號,其對應的archetype爲maven-archetype-quickstart,我們直接回車以選擇該archetype,緊接着Maven會提示我們輸入要創建項目的groupId、artifactId、 version、以及包名package,如下輸入並確認:

  1. Define value for groupId: : com.juvenxu.mvnbook  
  2. Define value for artifactId: : hello-world  
  3. Define value for version:  1.0-SNAPSHOT: :  
  4. Define value for package:  com.juvenxu.mvnbook: : com.juvenxu.mvnbook.helloworld  
  5. Confirm properties configuration:  
  6. groupId: com.juvenxu.mvnbook  
  7. artifactId: hello-world  
  8. version: 1.0-SNAPSHOT  
  9. package: com.juvenxu.mvnbook.helloworld  
  10.  Y: : Y  

Archetype插件將根據我們提供的信息創建項目骨架。在當前目錄下,Archetype插件會創建一個名爲hello-world(我們定義的artifactId)的子目錄,從中可以看到項目的基本結構:基本的pom.xml已經被創建,裏面包含了必要的信息以及一個junit依賴;主代碼目錄src/main/java已經被創建,在該目錄下還有一個Java類com.juvenxu.mvnbook.helloworld.App,注意這裏使用到了我們剛纔定義的包名,而這個類也僅僅只有一個簡單的輸出Hello World!的main方法;測試代碼目錄src/test/java也被創建好了,並且包含了一個測試用例com.juvenxu.mvnbook.helloworld.AppTest

Archetype可以幫助我們迅速地構建起項目的骨架,在前面的例子中,我們完全可以在Archetype生成的骨架的基礎上開發Hello World項目以節省我們大量時間。

此外,我們這裏僅僅是看到了一個最簡單的archetype,如果你有很多項目擁有類似的自定義項目結構以及配置文件,你完全可以一勞永逸地開發自己的archetype,然後在這些項目中使用自定義的archetype來快速生成項目骨架,本書後面的章節會詳細闡述如何開發Maven Archetype。

3.6 m2eclipse簡單使用 Top

介紹前面Hello World項目的時候,我們並沒有涉及IDE,如此簡單的一個項目,使用最簡單的編輯器也能很快完成,但對於稍微大一些的項目來說,沒有IDE就是不可想象的,本節我們先介紹m2eclipse的基本使用。

3.6.1 導入Maven項目

第2章介紹瞭如何安裝m2eclipse,現在,我們使用m2ecilpse導入Hello World項目。選擇菜單項File,然後選擇Import,我們會看到一個Import對話框,在該對話框中選擇General目錄下的Maven Projects,然後點擊Next,就會出現Import Projects對話框,在該對話框中點擊Browse…選擇Hello World的根目錄(即包含pom.xml文件的那個目錄),這時對話框中的Projects:部分就會顯示該目錄包含的Maven項目,如圖3-1所示:


 圖3-1 在Eclipse中導入Maven項目

點擊Finish之後,m2ecilpse就會將該項目導入到當前的workspace中,導入完成之後,我們就可以在Package Explorer視圖中看到如圖3-2所示的項目結構:

 圖3-2 Eclipse中導入的Maven項目結構

我們看到主代碼目錄src/main/java和測試代碼目錄src/test/java成了Eclipse中的資源目錄,包和類的結構也十分清晰,當然pom.xml永遠在項目的根目錄下,而從這個視圖中我們甚至還能看到項目的依賴junit-4.7.jar,其實際的位置指向了Maven本地倉庫(這裏我自定義了Maven本地倉庫地址爲D:\java\repository,後續章節會介紹如何自定義本地倉庫位置)。

3.6.2 創建Maven項目

創建一個Maven項目也十分簡單,選擇菜單項File -> New -> Other,在彈出的對話框中選擇Maven下的Maven Project,然後點擊Next >,在彈出的New Maven Project對話框中,我們使用默認的選項(不要選擇Create a simple project選項,那樣我們就能使用Maven Archetype),點擊Next >,此時m2eclipse會提示我們選擇一個Archetype,我們選擇maven-archetype-quickstart,再點擊Next >。由於m2eclipse實際上是在使用maven-archetype-plugin插件創建項目,因此這個步驟與上一節我們使用archetype創建項目骨架類似,輸入groupId,、artifactId、version、package(暫時我們不考慮Properties),如圖3-3所示:


 圖3-3 在Eclipse中使用Archetype創建項目

注意,爲了不和前面已導入的Hello World項目產生衝突和混淆,我們使用不同的artifactId和package。OK,點擊Finish,Maven項目就創建完成了,其結構與前一個已導入的Hello World項目基本一致。

3.6.3 運行mvn命令

我們需要在命令行輸入如mvn clean install之類的命令來執行maven構建,m2eclipse中也有對應的功能,在Maven項目或者pom.xml上右擊,再選擇Run As,就能看到如下的常見Maven命令,如圖3-4所示:


 圖3-4 在Eclipse中運行默認mvn命令

選擇想要執行的Maven命令就能執行相應的構建,同時我們也能在Eclipse的console中看到構建輸出。這裏常見的一個問題是,默認選項中沒有我們想要執行的Maven命令怎麼辦?比如,默認帶有mvn test,但我們想執行mvn clean test,很簡單,選擇Maven buid… 以自定義Maven運行命令,在彈出對話框中的Goals一項中輸入我們想要執行的命令,如clean test,設置一下Name,點擊Run即可。並且,下一次我們選擇Maven build,或者使用快捷鍵Alt + Shift + X, M快速執行Maven構建的時候,上次的配置直接就能在歷史記錄中找到。圖3-5就是自定義Maven運行命令的界面:


 圖3-5 在Eclipse中自定義mvn命令

3.7 NetBeans Maven插件簡單使用 Top

NetBeans的Maven插件也十分簡單易用,我們可以輕鬆地在NetBeans中導入現有的Maven項目,或者使用Archetype創建Maven項目,我們也能夠在NetBeans中直接運行mvn命令。

3.7.1 打開Maven項目

與其說打開Maven項目,不如稱之爲導入更爲合適,因爲這個項目不需要是NetBeans創建的Maven項目,不過這裏我們還是遵照NetBeans菜單中使用的名稱。

選擇菜單欄中的文件,然後選擇打開項目,直接定位到Hello World項目的根目錄,NetBeans會十分智能地識別出Maven項目,如圖3-6所示:


圖3-6 在NetBeans中導入Maven項目

Maven項目的圖標有別於一般的文件夾,點擊打開項目後,Hello World項目就會被導入到NetBeans中,在項目視圖中可以看到如圖3-7所示的項目結構:


 圖3-7 NetBeans中導入的Maven項目結構

NetBeans中項目主代碼目錄的名稱爲源包,測試代碼目錄成了測試包,編譯範圍依賴爲,測試範圍依賴爲測試庫,這裏我們也能看到pom.xml,NetBeans甚至還幫我們引用了settings.xml。

3.7.2 創建Maven項目

在NetBeans中創建Maven項目同樣十分輕鬆,在菜單欄中選擇文件,然後新建項目,在彈出的對話框中,選擇項目類別爲Maven,項目爲Maven項目,點擊“下一步”之後,對話框會提示我們選擇Maven原型(即Maven Archtype),我們選擇Maven快速啓動原型(1.0),(即前文提到的maven-archetype-quickstart),點擊“下一步”之後,輸入項目的基本信息,這些信息在之前討論archetype及在m2eclipse中創建Maven項目的時候都仔細解釋過,不再詳述,如圖3-8所示:


 圖3-8 在NetBeans中使用Archetype創建Maven項目

點擊完成之後,一個新的Maven項目就創建好了。

3.7.3 運行mvn命令

NetBeans在默認情況下提供兩種Maven運行方式,點擊菜單欄中的運行,我們可以看到生成項目清理並生成項目兩個選項,我們可以嘗試“點擊運行Maven構建”,根據NetBeans控制檯的輸出,我們就能發現它們實際上對應了mvn installmvn clean install兩個命令。

在實際開發過程中,我們往往不會滿足於這兩種簡單的方式,比如,有時候我們只想執行項目的測試,而不需要打包,這時我們就希望能夠執行mvn clean test命令,所幸的是NetBeans Maven插件完全支持自定義的mvn命令配置。

在菜單欄中選擇工具,接着選擇選項,在對話框中,最上面一欄選擇其他,下面選擇Maven標籤欄,在這裏我們可以對NetBeans Maven插件進行全局的配置(還記得第2章中我們如何配置NetBeans使用外部Maven麼?)。現在,選擇倒數第三行的編輯全局定製目標定義…,我們添加一個名爲Maven Test的操作,執行目標爲clean test,暫時不考慮其他配置選項,如圖3-9所示:

 

圖3-9 在NetBeans中自定義mvn命令

點擊“缺省保存該配置”,在Maven項目上右擊,選擇定製,就能看到剛纔配置好的Maven運行操作,選擇Maven Test之後,終端將執行mvn clean test。值得一提的是,我們也可以在項目上右擊,選擇定製,再選擇目標…再輸入想要執行的Maven目標(如clean package),點擊確定之後NetBeans就會執行相應的Maven命令。這種方式十分便捷,但這是臨時的,該配置不會被保存,也不會有歷史記錄。

3.8 小結 Top

本章以儘可能簡單且詳細的方式敘述了一個Hello World項目,重點解釋了POM的基本內容、Maven項目的基本結構、以及構建項目基本的Maven命令。在此基礎上,還介紹瞭如何使用 Archetype快速創建項目骨架。最後講述的是如何在Eclipse和NetBeans中導入、創建及構建Maven項目。




原文轉載自:http://www.cnblogs.com/dcba1112/archive/2011/05/01/2033805.html
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章