1.1 何爲Maven/2 javascript
1.2 爲何須要Maven/4 html
1.3 Maven與極限編程/7
1.4 被誤解的Maven/8
1.5 小結/9 java
Maven這個詞能夠翻譯爲「知識的積累」,也能夠翻譯爲「專 家」或「內行」。本書將介紹Maven這一跨平臺的項目管理工具。做爲Apache組織中的一個頗爲成功的開源項目,Maven主要服務於基於Java平 臺的項目構建、依賴管理和項目信息管理。不管是小型的開源類庫項目,仍是大型的企業級應用;不管是傳統的瀑布式開發,仍是流行的敏捷模式,Maven都能 大顯身手。 git
無論你是否意識到,構建(build)是每一位程序員天天都在作的工做。早上來 到公司,咱們作的第一件事情就是從源碼庫簽出最新的源碼,而後進行單元測試,若是發現失敗的測試,會找相關的同事一塊兒調試,修復錯誤代碼。接着回到本身的 工做上來,編寫本身的單元測試及產品代碼,咱們會感激IDE隨時報出的編譯錯誤提示。
忙到午餐時間,代碼編寫得差很少了,測試也經過了,開心地享 用午飯,而後休息。下午先在昏昏沉沉中開了個例會,會議結束後喝杯咖啡繼續工做。剛纔在會上經理要求看測試報告,因而找了相關工具集成進IDE,生成了像 模像樣的測試覆蓋率報告,接着發了一封電子郵件給經理,鬆了口氣。誰料QA小組又發過來了幾個bug,沒辦法,先本地重現再說,因而熟練地用IDE生成了 一個WAR包,部署到Web容器下,啓動容器。看到熟悉的界面了,遵循bug報告,一步步重現了bug……快下班的時候,bug修好了,提交代碼,通知 QA小組,在愉快中結束了一天的工做。 程序員
仔細總結一下,咱們會發現,除了編寫源代碼,咱們天天有至關一部分時間花在了編 譯、運行單元測試、生成文檔、打包和部署等煩瑣且不起眼的工做上,這就是構建。若是咱們如今還手工這樣作,那成本也過高了,因而有人用軟件的方法讓這一系 列工做徹底自動化,使得軟件的構建能夠像全自動流水線同樣,只須要一條簡單的命令,全部煩瑣的步驟都可以自動完成,很快就能獲得最終結果。 web
前面介紹了Maven的用途之一是服務於構建,它是一個異常強大的構建工具,能 夠幫咱們自動化構建過程,從清理、編譯、測試到生成報告,再到打包和部署。咱們不須要也不該該一遍又一遍地輸入命令,一次又一次地點擊鼠標,咱們要作的是 使用Maven配置好項目,而後輸入簡單的命令(如mvn clean install),Maven會幫咱們處理那些煩瑣的任務。 spring
Maven是跨平臺的,這意味着不管是在Windows上,仍是在Linux或者Mac上,均可以使用一樣的命令。 shell
咱們一直在不停地尋找避免重複的方法。設計的重複、編碼的重複、文檔的重複,當 然還有構建的重複。Maven最大化地消除了構建的重複,抽象了構建生命週期,而且爲絕大部分的構建任務提供了已實現的插件,咱們再也不須要定義過程,甚至 不須要再去實現這些過程當中的一些任務。最簡單的例子是測試,咱們不必告訴Maven去測試,更不須要告訴Maven如何運行測試,只須要遵循Maven 的約定編寫好測試用例,當咱們運行構建的時候,這些測試便會自動運行。 apache
想象一下,Maven抽象了一個完整的構建生命週期模型,這個模型吸收了大量其 他的構建腳本和構建工具的優勢,總結了大量項目的實際需求。若是遵循這個模型,能夠避免不少沒必要要的錯誤,能夠直接使用大量成熟的Maven插件來完成我 們的任務(不少時候咱們可能都不知道本身在使用Maven插件)。此外,若是有很是特殊的需求,咱們也能夠輕鬆實現本身的插件。 編程
Maven還有一個優勢,它能幫助咱們標準化構建過程。在Maven以前,十個項目可能有十種構建方式;有了Maven以後,全部項目的構建命令都是簡單一致的,這極大地避免了沒必要要的學習成本,並且有利於促進項目團隊的標準化。
綜上所述,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)。
Maven不是Java領域惟一的構建管理的解決方案。本節將經過一些簡單的例子解釋Maven的必要性,並介紹其餘構建解決方案,如IDE、Make和Ant,並將它們與Maven進行比較。
筆者初中時開始接觸計算機,到了高中時更是求之不得但願擁有一臺本身的計算機。個人第一臺計算機是賽揚733的,選購是一個漫長的過程,我先閱讀了大量的雜誌以瞭解各種配件的優劣,CPU、內存、主板、顯卡,甚至聲卡,我都仔細地挑選,後來還跑了不少商家,調貨、討價還價,組裝好後本身裝操做系統和驅動程序……雖然這花費了我大量時間,但我很享受這個過程。但是事實證實,裝出來的機器穩定性不怎麼好。
一年前我須要配一臺工做站,這時候我已經沒有太多時間去研究電腦配件了。我選擇了某知名PC供應商的在線商店,大概瀏覽了一下主流的機型,選擇了我須要的配置,而後下單、付款。接着PC供應商幫我組裝電腦、安裝操做系統和驅動程序。一週後,物流公司將電腦送到個人家裏,我接上顯示器、電源、鼠標和鍵盤就能直接使用了。這爲我節省了大量時間,並且這臺電腦十分穩定,商家在把電腦發送給我以前已經進行了很好的測試。對了,我還能享受兩年的售後服務。
使用腳本創建高度自定義的構建系統就像買組裝PC,耗時費力,結果也不必定很好。固然,你能夠享受從無到有的樂趣,但恐怕實際項目中沒法給你那麼多時間。使用Maven就像購買品牌PC,省時省力,並能獲得成熟的構建系統,還能獲得來自於Maven社區的大量支持。惟一與購買品牌PC不一樣的是,Maven是開源的,你無須爲此付費。若是有興趣,你還能去了解Maven是如何工做的,而咱們沒法知道那些PC巨頭的商業祕密。
固然,咱們沒法否定優秀的IDE能大大提升開發效率。當前主流的IDE如Eclipse和NetBeans等都提供了強大的文本編輯、調試甚至重構功能。雖然使用簡單的文本編輯器和命令行也能完成絕大部分開發工做,但不多有人願意那樣作。然而,IDE是有其天生缺陷的:
咱們應該合理利用IDE,而不是過多地依賴它。對於構建這樣的任務,在IDE中一次次地點擊鼠標是愚蠢的行爲。Maven是這方面的專家,並且主流IDE都集成了Maven,咱們能夠在IDE中方便地運行Maven執行構建。
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的基本結構以下:
Make經過一系列目標和依賴將整個構建過程串聯起來,同時利用本地命令完成每一個目標的實際行爲。Make的強大之處在於它能夠利用全部系統的本地命令,尤爲是UNIX/Linux系統,豐富的功能、強大的命令可以幫助Make快速高效地完成任務。
可是,Make將本身和操做系統綁定在一塊兒了。也就是說,使用Make,就不能實現(至少很難)跨平臺的構建,這對於Java來講是很是不友好的。此外,Makefile的語法也成問題,不少人抱怨Make構建失敗的緣由每每是一個難以發現的空格或Tab使用錯誤。
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用戶無須進行任何配置就能夠直接享用。
【該小節內容整理自網友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」?
極限編程(XP)是近些年在軟件行業紅得發紫的敏捷開發方法,它強調擁抱變化。該軟件開發方法的創始人Kent Beck提出了XP所追求的價值、實施原則和推薦實踐。下面看一下Maven是如何適應XP的。
首先看一下Maven如何幫助XP團隊實現一些核心價值:
此外,Maven更能無縫地支持或者融入到一些主要的XP實踐中:
上述這些實踐並不是只在XP中適用。事實上,除了其餘敏捷開發方法如SCRUM以外,幾乎任何軟件開發方法都能借鑑這些實踐。也就是說,Maven幾乎可以很好地支持任何軟件開發方法。
例 如,在傳統的瀑布模型開發中,項目依次要經歷需求開發、分析、設計、編碼、測試和集成發佈階段。從設計和編碼階段開始,就可使用Maven來創建項目的 構建系統。在設計階段,也徹底能夠針對設計開發測試用例,而後再編寫代碼來知足這些測試用例。然而,有了自動化構建系統,咱們能夠節省不少手動的測試時 間。此外,儘早地使用構建系統集成團隊的代碼,對項目也是百利而無一害。最後,Maven還能幫助咱們快速地發佈項目。
第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 小結
在安裝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節。
請訪問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吧!
將安裝文件解壓到你指定的目錄中,如:
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執行腳本。
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環境變量指向舊版本的安裝目錄。
Maven是跨平臺的,它能夠在任何一種主流的操做系統上運行,本節將介紹如何在基於Unix的系統(包括Linux、Mac OS以及FreeBSD等)上安裝Maven。
首先,與在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安裝
在基於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進行檢查。
本章前面的內容講述瞭如何在各類操做系統中安裝和升級Maven。如今咱們來仔細分析一下Maven的安裝文件。
前面咱們講到設置M2_HOME環境變量指向Maven的安裝目錄,本書以後全部使用M2_HOME的地方都指代了該安裝目錄,讓咱們看一下該目錄的結構和內容:
bin
boot
conf
lib
LICENSE.txt
NOTICE.txt
README.txt
在講述該小節以前,咱們先運行一條簡單的命令: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。這是一條最佳實踐,咱們將在本章最後一小節詳細解釋。
有時候你所在的公司因爲安全因素考慮,要求你使用經過安全認證的代理訪問因特網。這種狀況下,就須要爲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結尾的域名訪問都不要經過代理。
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. 重要的
2. 不重要的
讀者能夠根據本身的須要安裝相應組件,具體步驟再也不贅述。
待安裝完畢後,重啓Eclipse,如今讓咱們驗證一下m2eclipse是否正確安裝了。首先,點擊菜單欄中的Help,而後選擇About Eclipse,在彈出的對話框中,點擊Installation Details按鈕,會獲得一個對話框,在Installed Software標籤欄中,檢查剛纔咱們選擇的模塊是否在這個列表中,如圖2-9所示:
圖2-9m2eclipse安裝結果
若是一切沒問題,咱們再檢查一下Eclipse如今是否已經支持建立Maven項目,依次點擊菜單欄中的File→New→Other,在彈出的對話框中,找到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
本小節會先介紹如何在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已經正確安裝了。
本節介紹一些在安裝Maven過程當中不是必須的,但十分有用的實踐。
本章前面介紹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安裝目錄下的文件。
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文件。
不管是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
本章詳細介紹了在各類操做系統平臺上安裝Maven,並對Maven安裝目錄進行了深刻的分析,在命令行的基礎上,本章又進一步介紹了Maven與主流IDE Eclipse及NetBeans的集成,本章最後還介紹了一些與Maven安裝相關的最佳實踐。本書下一章會建立一個Hello World項目,帶領讀者配置和構建Maven項目。
就像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
代碼的第一行是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的修改。
項目主代碼和測試代碼不一樣,項目的主代碼會被打包到最終的構件中(好比jar),而測試代碼只在運行測試時用到,不會被打包。默認狀況下,Maven假設項目主代碼位於src/main/java目錄,咱們遵循Maven的約定,建立該目錄,而後在該目錄下建立文件com/juvenxu/mvnbook/helloworld/HelloWorld.java,其內容如代碼清單3-2:
代碼清單3-2:Hello World的主代碼
這是一個簡單的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 ,咱們會獲得以下輸出:
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.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添加依賴
代碼中添加了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的測試代碼
一個典型的單元測試包含三個步驟:一,準備測試類及數據;二,執行要測試的行爲;三,檢查結果。上述樣例中,咱們首先初始化了一個要測試的HelloWorld實例,接着執行該實例的sayHello()方法並保存結果到result變量中,最後使用JUnit框架的Assert類檢查結果是否爲咱們指望的」Hello Maven」。在JUnit 3中,約定全部須要執行測試的方法都以test開頭,這裏咱們使用了JUnit 4,但咱們仍然遵循這一約定,在JUnit 4中,須要執行的測試方法都應該以@Test 進行標註。
測試用例編寫完畢以後就能夠調用Maven執行測試,運行 mvn clean test :
不幸的是構建失敗了,不過咱們先耐心分析一下這段輸出(爲了本書的簡潔,一些不重要的信息我用省略號略去了)。命令行輸入的是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
該POM省略了除插件配置之外的其餘部分,咱們暫且不去關心插件配置的細節,只須要知道compiler插件支持Java 5的編譯。如今再執行mvn clean test,輸出以下:
咱們看到compiler:testCompile任務執行成功了,測試代碼經過編譯以後在target/test-classes下生成了二進制文件,緊接着surefire:test任務運行測試,surefire是Maven世界中負責執行測試的插件,這裏它運行測試用例HelloWorldTest,而且輸出測試報告,顯示一共運行了多少測試,失敗了多少,出錯了多少,跳過了多少。顯然,咱們的測試經過了——BUILD SUCCESSFUL。
將項目進行編譯、測試以後,下一個重要步驟就是打包(package)。Hello World的POM中沒有指定打包類型,使用默認打包類型jar,咱們能夠簡單地執行命令mvn clean package 進行打包,能夠看到以下輸出:
相似地,Maven會在打包以前執行編譯、測試等操做。這裏咱們看到jar:jar任務負責打包,實際上就是jar插件的jar目標將項目主代碼打包成一個名爲hello-world-1.0-SNAPSHOT.jar的文件,該文件也位於target/輸出目錄中,它是根據artifact-version.jar規則進行命名的,若有須要,咱們還可使用finalName來自定義該文件的名稱,這裏暫且不展開,本書後面會詳細解釋。
至此,咱們獲得了項目的輸出,若是有須要的話,就能夠複製這個jar文件到其餘項目的Classpath中從而使用HelloWorld類。可是,如何才能讓其餘的Maven項目直接引用這個jar呢?咱們還須要一個安裝的步驟,執行 mvn clean install:
在打包以後,咱們又執行了安裝任務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,配置該插件以下:
plugin元素在POM中的相對位置應該在<project><build><plugins>下面。咱們配置了mainClass爲com.juvenxu.mvnbook.helloworld.HelloWorld,項目在打包時會將該信息放到MANIFEST中。如今執行 mvn clean install ,待構建完成以後打開target/目錄,咱們能夠看到hello-world-1.0-SNAPSHOT.jar和original-hello-world-1.0-SNAPSHOT.jar,前者是帶有Main-Class信息的可運行jar,後者是原始的jar,打開hello-world-1.0-SNAPSHOT.jar的META-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項目結構、以及如何編譯、測試、打包,等等。
Hello World項目中有一些Maven的約定:在項目的根目錄中放置pom.xml,在src/main/java目錄中放置項目的主代碼,在src/test/java中放置項目的測試代碼。我之因此一步一步地展現這些步驟,是爲了能讓多是Maven初學者的你獲得最實際的感覺。咱們稱這些基本的目錄結構和pom.xml文件內容稱爲項目的骨架,當你第一次建立項目骨架的時候,你還會饒有興趣地去體會這些默認約定背後的思想,第二次,第三次,你也許還會滿意本身的熟練程度,但第4、第五次作一樣的事情,就會讓程序員惱火了,爲此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,以下輸入並確認:
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。
介紹前面Hello World項目的時候,咱們並無涉及IDE,如此簡單的一個項目,使用最簡單的編輯器也能很快完成,但對於稍微大一些的項目來講,沒有IDE就是不可想象的,本節咱們先介紹m2eclipse的基本使用。
第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,後續章節會介紹如何自定義本地倉庫位置)。
以eclipse3.6爲例
1)建立簡單Maven項目
點擊Eclipse菜單欄File->New->Ohter->Maven獲得以下圖所示對話框:
選中Maven Project並點擊Next,到下一個對話框繼續點擊Next獲得以下對話框
如圖示操做,選擇maven-archetype-quickstart,點擊Next
按圖示填寫好groupId, artfactId,version等信息,點擊Finish。
由此咱們成功建立了一個簡單的Maven項目,項目結構如圖所示
2)建立Maven web項目
操做跟建立簡單Maven項目相似,點擊Eclipse菜單File->New->Other->Maven->Maven Project
在選擇maven-archetype的界面進行以下操做:
點擊Next,填寫好相應的groupId,artifactId,version等信息,點擊Finish
獲得的Maven web項目結構以下圖所示:
右擊項目,點擊Properties->Project Facets
如上圖能夠看到項目爲web2.3 java1.5 固然咱們也能夠改爲咱們所須要的版本,打開xml文件my-app-web/.settings/org.eclipse.wst.common.project.facet.core.xml,進行修改便可:
3)導入Maven項目
在Eclipse project explorer中右擊,在彈出框中選擇import,獲得以下圖所示:
選擇Existing Maven Projects,並點擊Next,獲得以下圖所示對話框:
選擇一個已經建立好的Maven項目,並點擊Finish。
由此,導入Maven項目成功
3. 運行Maven命令
右擊項目,點擊Run as,以下圖:
便可看到有不少現有的maven命令,點擊便可運行,並在控制檯能夠看到運行信息
若是你想運行的maven命令在這裏沒有找到,點擊Maven build建立新的命令,操做以下圖所示:
以下圖填入Maven命令,點擊Run便可
新增的maven命令能夠經過以下方式找到,並再次運行:
咱們須要在命令行輸入如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命令
NetBeans的Maven插件也十分簡單易用,咱們能夠輕鬆地在NetBeans中導入現有的Maven項目,或者使用Archetype建立Maven項目,咱們也可以在NetBeans中直接運行mvn命令。
與其說打開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。
在NetBeans中建立Maven項目一樣十分輕鬆,在菜單欄中選擇文件,而後新建項目,在彈出的對話框中,選擇項目類別爲Maven,項目爲Maven項目,點擊「下一步」以後,對話框會提示咱們選擇Maven原型(即Maven Archtype),咱們選擇Maven快速啓動原型(1.0),(即前文提到的maven-archetype-quickstart),點擊「下一步」以後,輸入項目的基本信息,這些信息在以前討論archetype及在m2eclipse中建立Maven項目的時候都仔細解釋過,再也不詳述,如圖3-8所示:
圖3-8 在NetBeans中使用Archetype建立Maven項目
點擊完成以後,一個新的Maven項目就建立好了。
NetBeans在默認狀況下提供兩種Maven運行方式,點擊菜單欄中的運行,咱們能夠看到生成項目和清理並生成項目兩個選項,咱們能夠嘗試「點擊運行Maven構建」,根據NetBeans控制檯的輸出,咱們就能發現它們實際上對應了mvn install和mvn 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命令。這種方式十分便捷,但這是臨時的,該配置不會被保存,也不會有歷史記錄。