Maven,一個意爲accumulator of knowledge的猶太詞,起初只是爲了簡化Jakarta Turbine項目中的構建流程。若干個項目擁有不一樣的Ant構建文件,咱們須要一個標準化方式來構建這些項目,一個清晰地定義項目的組成的方式、一個簡單的發佈項目信息的方式和跨項目共享JAR文件的方式。這就是如今可用於構建和管理任意基於JAVA的項目的工具。咱們但願創造能簡化Java開發者日復一日的工做的東西,而且幫助人們理解任意基於Java的項目。 html
Maven的基本目標是讓一個開發者在最短期內理解一個開發任務的完整狀態。爲了達到這個目標,Maven嘗試解決了幾個值得關注的領域: java
注意,如下是關於Maven的錯誤理解: 程序員
Maven是一個項目管理和構建自動化工具。對於程序員來講,最關心的是它的項目構建功能。 數據庫
Maven採用純Java編寫。採用了POM(project object model)概念來管理項目,全部項目配置信息都被定義在pom.xml的文件中。因爲Maven的面向項目的方法,目前Apache下絕大多數項目都已採用Maven管理。Maven還支持多種插件。 apache
Maven使用慣例優於配置的原則。它要求在沒有定製以前,全部項目都有以下結構: 瀏覽器
一個maven項目在默認狀況下會產生JAR文件。 服務器
Ant的項目管理工具(做爲make的替代工具)不能知足絕大多數開發人員的須要。經過檢查ant構建文件,很難發現項目的相關性信息和其它元信息(如開發人員,版本或站點主頁等)。 網絡
Maven除了以程序構建能力爲特點以外,還提供了Ant所缺乏的高級項目管理工具。因爲Maven的缺省構建規則有較高的可重用性,因此經常用兩三行腳本就能夠構建簡單項目,比Ant簡潔。 併發
Maven和Ant針對構建問題的兩個不一樣方面。Ant爲Java技術開發項目提供跨平臺構建任務。Maven自己描述項目的高級方面,它從Ant借用了絕大多數構建任務。它們表明兩個差別很大的工具,如下是等同組件之間的區別: oracle
首先保證已安裝JDK: http://www.oracle.com/technetwork/cn/java/javase/downloads/index.html
Maven官網: http://maven.apache.org/download.cgi
最新的Maven版本是3.3.9,系統要求:JDK1.7。
下載apache-maven-3.3.9-bin.zip,並解壓。而後將apache-maven-3.3.9目錄下的bin文件夾路徑,添加到環境變量path中。
在cmd中驗證配置成功:
注意,若是第一次運行maven,須要Internet鏈接,由於maven須要從網絡下載插件。插件默認的存放路徑是: C:\Users\YourUserName\.m2\repository。
mvn archetype:generate
maven提供了archetype來幫助咱們快速勾勒出項目骨架。
注意,若是是maven2,最好指定archetype的版本,使用命令:mvn org.apache.maven.plugins:maven-archetype-plugin:2.0-alpha-5:generate。由於maven2不會自動解析最新的穩定版本,會自動下載最新版本,可能獲得不穩定的SNAPSHOT版本,致使運行失敗。實際運行的是插件:maven-archetype-plugin,注意冒號的分隔,其格式爲groupId:artifactId:version:goal,org.apache.maven.plugins是maven官方插件的groupId,maven-archetype-plugin是archetype插件的artifactId,2.0-alpha-5是目前該插件最新的穩定版本,generate是要使用的插件目標。
輸入上述命令後,會看到一段長長的輸出,有不少可用的archetype供選擇,每個archetype前面都會對應有一個編號,同時命令行會提示一個默認的編號,其對應的archetype爲maven-archetype-quickstart,直接回車以選擇該archetype,緊接着maven會提示輸入要建立項目的groupId,artifactId,version以及包名package。
也能夠直接使用以下命令,一次把groupId, artifactId, version, package參數都設定:
mvn archetype:generate -DgroupId=com.mycompany.helloworld -DartifactId=helloworld -Dpackage=com.mycompany.helloworld -Dversion=1.0-SNAPSHOT
最終生成的項目結構以下圖所示。
【POM文件】pom.xml,存放在項目目錄下。
archetype插件創建了一個helloworld項目,這個名字來自artifactId。在這個目錄下有,有一個pom.xml文件,用於描述項目、配置插件和管理依賴關係。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.bupt.helloworld</groupId>
<artifactId>helloworld</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>helloworld</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
【源代碼和資源】默認生成App.java文件, 放在src/main下。
package com.bupt.helloworld;
/**
* Hello world!
*
*/
public class App
{
public static void main( String[] args )
{
System.out.println( "Hello World!" );
}
}
【測試代碼和資源】放在src/test下。此處略。
進入項目目錄,構建:
cd helloworld
mvn package
注意第一次運行maven,會從網上的maven庫下載須要的程序,放在本地庫中。默認的本地庫是%USER_HOME%\.m2\repository\。
構建成功後,項目目錄下出現了一個新的目錄 target,構建打包後的jar文件就放在該目錄下。編譯後的class文件放在target/classes/目錄下。測試class文件放在target/test-classes目錄下。
注:-cp和-classpath同樣,是指定類運行所依賴其餘類的路徑,一般是類庫、jar包等。這裏用到的是helloworld-1.0-SNAPSHOT.jar包。
Maven是基於構建生命週期的核心概念的。即,構建和部署一個特定項目的流程是清晰定義的。對於項目構建者來講,這意味着只須要學習一小部分命令就能夠構建任意maven項目,POM會保證他們得到想要的結果。
項目構建中進行的清理、編譯、測試及部署能夠視做一個個生命週期,但每一個項目每一個人都有不一樣的實現方式。Maven的生命週期就是對全部構建過程進行抽象和統一。
生命週期和插件是協同工做的。Maven命令的輸入每每對應了生命週期,如mvn compile表示執行默認生命週期的階段compile。Maven的生命週期是抽象的,實際行爲由插件完成,如mvn compile可能由maven-compile-plugin完成。
有三套相互獨立的內置的生命週期:default,clean,site。
每一個構建生命週期都是由一個不一樣的構建phases序列組成的。一個build phase表明該生命週期中的一個階段。平時在命令行輸入的命令總會對應於一個特定的階段,好比,mvn clean,這裏的clean是指clean生命週期中的clean階段。在一個生命週期中,運行某個階段時,它以前的全部階段都會被運行,也就是說,mvn clean等同於mvn pre-clean clean。若是咱們運行mvn post-clean,那麼pre-clean,clean都會先執行。——這是Maven很重要的一個規則。
Maven從本質上來講是一個執行插件的框架。Maven的核心文件很小,主要任務都是由插件來完成的。例如:%local repository%\org\apache\maven\plugins能夠看到一些下載好的插件:
Maven的插件通常分爲構建插件Build Plugins,和報告插件Reporting Plugins。構建插件在構建過程當中執行,它們在POM的<build/>標籤下配置。報告插件在站點生成過程執行,它們在<reporting/>標籤下配置。由於報告插件的結果是站點生成的一部分,報告插件應該同時是國際化和本地化的。
更多關於插件的詳細信息,見http://maven.apache.org/plugins/index.html
一個插件一般能夠完成多個任務,每個任務就叫作插件的一個目標。
例如,編譯源代碼是由maven-compiler-plugin完成的,compile目標用來編譯位於src/main/java目錄下的主源碼,testCompile目標用來編譯位於src/test/java目錄下的測試源碼。
執行mvn install時,調用的插件和插件目標以下:
用戶能夠經過兩種方式調用插件目標。第一種是將插件目標與生命週期階段lifecycle phase綁定,這樣用戶在命令行只是輸入生命週期階段而已。例如,Maven默認將maven-compiler-plugin的compile目標與compile生命週期階段綁定,所以,命令mvn compile其實是先定位到compile這一輩子命週期階段,而後再根據綁定關係調用maven-compiler-plugin的compile目標。
第二種方式是直接在命令行指定要執行的插件目標,例如mvn archetype:generate就表示調用maven-archetype-plugin的generate目標,這種帶冒號的調用方式與生命週期無關。
Generate-resource |
Plugin:descriptor |
Process-resource |
Resources:resources |
Compile |
Compiler:compile |
Process-test-resources |
Resources:testResources |
Test-Compile |
Compiler:testCompile |
Test |
Surefire:test |
Package |
Jar:jar && plugin:addPluginArtifactMetadata |
Install |
Install:install |
Deploy |
Deploy:deploy |
例如,將maven-source-plugin的jar-no-fork目標綁定到生命週期的package階段,這樣,之後執行mvn package命令打包項目時,在package以後會執行源代碼打包,生成.jar源碼包。
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<id>attach-source</id>
<phase>package</phase><!-- 要綁定到的生命週期的階段 -->
<goals>
<goal>jar-no-fork</goal><!-- 要綁定的插件的目標 -->
</goals>
</execution>
</executions>
</plugin>
</plugins>
……
</build>
讓用戶在Maven項目中運行ant任務。用戶能夠直接以ant的方式編寫target,而後交給該插件的run目標去執行。在一些由ant向maven遷移的項目中,該插件尤爲有用。此外,當須要編寫一些自定義程度很高的任務,同時又以爲maven不夠靈活時,也能夠以ant的方式實現之。
Archetype指項目的骨架。前面的命令mvn archetype:generate,實際上就是讓maven-archetype-plugin生成一個簡單的項目骨架,幫助開發者快速上手。Generate目標使用交互的方式提示用戶輸入必要的信息,以建立項目,體驗更好。此外,還有其餘目標幫助用戶自定義項目原型,例如,你有一個產品要交付給不少客戶進行二次開發,就能夠爲他們提供一個archetype。
用於製做項目分發包。該分發包可能包含了項目的可執行文件、源代碼、readme、平臺腳本等等。maven-assembly-plugin支持各類主流的格式,如zip, tar.gz, jar和war等,具體打包哪些文件是高度可控的,例如用戶可按文件級別的粒度、文件集級別的粒度、模塊級別的粒度、以及依賴級別的粒度控制打包。此外,包含和排除配置也是支持的。maven-assembly-plugin要求用戶使用一個名爲assembly.xml的元數據文件來表述打包,它的single目標能夠直接在命令行調用,也能夠被綁定至生命週期。
最大的用途是分析項目依賴。
建立一系列規則,強制你們遵照,包括設定java版本,設定maven版本,禁止某些依賴,禁止SNAPSHOT依賴。只要在一個父POM配置規則,而後讓你們繼承,當規則被破壞時,maven就會報錯。除了標準的規則以外,你還能夠擴展該插件,編寫本身的規則。
maven-enforcer-plugin的enforce目標負責檢查規則,它默認綁定到生命週期的validate階段。
一個小巧的輔助工具,最簡單的help:system能夠打印全部可用的環境變量和java系統屬性。help:effective-pom和help:effective-settings最爲有用,它們分別打印項目的有效POM和有效settings,有效POM是指合併了全部父POM(包括Super POM)後的XML,當你不肯定POM的某些信息從何而來時,就能夠查看有效POM。有效settings同理,特別是當你發現本身配置的settings.xml沒有生效時,就能夠用help:effective-settings來驗證。此外,maven-help-plugin的describe目標能夠幫助你描述任何一個Maven插件的信息,還有all-profiles目標和active-profiles目標幫助查看項目的Profile。
幫助自動化項目版本發佈,它依賴於POM中的SCM信息。release:prepare用來準備版本發佈,具體的工做包括檢查是否有未提交代碼、檢查是否有SNAPSHOT依賴、升級項目的SNAPSHOT版本至RELEASE版本、爲項目打標籤等等。release:perform則是簽出標籤中的RELEASE源碼,構建併發布。版本發佈是很是瑣碎的工做,它涉及了各類檢查,並且因爲該工做僅僅是偶爾須要,所以手動操做很容易遺漏一些細節,maven-release-plugin讓該工做變得很是快速簡便,不易出錯。maven-release-plugin的各類目標一般直接在命令行調用,由於版本發佈顯然不是平常構建生命週期的一部分。
爲了使項目結構更爲清晰,Maven區別對待Java代碼文件和資源文件,maven-compiler-plugin用來編譯Java代碼,maven-resources-plugin則用來處理資源文件。默認的主資源文件目錄是src/main/resources
,不少用戶會須要添加額外的資源文件目錄,這個時候就能夠經過配置maven-resources-plugin來實現。此外,資源文件過濾也是Maven的一大特性,你能夠在資源文件中使用${propertyName}形式的Maven屬性,而後配置maven-resources-plugin開啓對資源文件的過濾,以後就能夠針對不一樣環境經過命令行或者Profile傳入屬性的值,以實現更爲靈活的構建。
多是因爲歷史的緣由,Maven 2/3中用於執行測試的插件不是maven-test-plugin,而是maven-surefire-plugin。其實大部分時間內,只要你的測試類遵循通用的命令約定(以Test結尾、以TestCase結尾、或者以Test開頭),就幾乎不用知曉該插件的存在。然而在當你想要跳過測試、排除某些測試類、或者使用一些TestNG特性的時候,瞭解maven-surefire-plugin的一些配置選項就頗有用了。例如 mvn test -Dtest=FooTest 這樣一條命令的效果是僅運行FooTest測試類,這是經過控制maven-surefire-plugin的test參數實現的。
Maven默認只容許指定一個主Java代碼目錄和一個測試Java代碼目錄,雖然這實際上是個應當儘可能遵照的約定,但偶爾你仍是會但願可以指定多個源碼目錄(例如爲了應對遺留項目),build-helper-maven-plugin的add-source目標就是服務於這個目的,一般它被綁定到默認生命週期的generate-sources階段以添加額外的源碼目錄。須要強調的是,這種作法仍是不推薦的,由於它破壞了 Maven的約定,並且可能會遇到其餘嚴格遵照約定的插件工具沒法正確識別額外的源碼目錄。
build-helper-maven-plugin的另外一個很是有用的目標是attach-artifact,使用該目標你能夠以classifier的形式選取部分項目文件生成附屬構件,並同時install到本地倉庫,也能夠deploy到遠程倉庫。
exec-maven-plugin很好理解,顧名思義,它能讓你運行任何本地的系統程序,在某些特定狀況下,運行一個Maven外部的程序可能就是最簡單的問題解決方案,這就是exec:exec的用途,固然,該插件還容許你配置相關的程序運行參數。除了exec目標以外,exec-maven-plugin還提供了一個java目標,該目標要求你提供一個mainClass參數,而後它可以利用當前項目的依賴做爲classpath,在同一個JVM中運行該mainClass。有時候,爲了簡單的演示一個命令行Java程序,你能夠在POM中配置好exec-maven-plugin的相關運行參數,而後直接在命令運行 mvn exec:java 以查看運行效果。
在進行Web開發的時候,打開瀏覽器對應用進行手動的測試幾乎是沒法避免的,這種測試方法一般就是將項目打包成war文件,而後部署到Web容器中,再啓動容器進行驗證,這顯然十分耗時。爲了幫助開發者節省時間,jetty-maven-plugin應運而生,它徹底兼容 Maven項目的目錄結構,可以週期性地檢查源文件,一旦發現變動後自動更新到內置的Jetty Web容器中。作一些基本配置後(例如Web應用的contextPath和自動掃描變動的時間間隔),你只要執行 mvn jetty:run ,而後在IDE中修改代碼,代碼經IDE自動編譯後產生變動,再由jetty-maven-plugin偵測到後更新至Jetty容器,這時你就能夠直接測試Web頁面了。須要注意的是,jetty-maven-plugin並非宿主於Apache或Codehaus的官方插件,所以使用的時候須要額外的配置settings.xml
的pluginGroups元素,將org.mortbay.jetty這個pluginGroup加入。
不少Maven用戶遇到過這樣一個問題,當項目包含大量模塊的時候,爲他們集體更新版本就變成一件煩人的事情,到底有沒有自動化工具能幫助完成這件事情呢?(固然你可使用sed之類的文本操做工具,不過不在本文討論範圍)答案是確定的,versions-maven- plugin提供了不少目標幫助你管理Maven項目的各類版本信息。例如最經常使用的,命令 mvn versions:set -DnewVersion=1.1-SNAPSHOT 就能幫助你把全部模塊的版本更新到1.1-SNAPSHOT。該插件還提供了其餘一些頗有用的目標,display-dependency- updates能告訴你項目依賴有哪些可用的更新;相似的display-plugin-updates能告訴你可用的插件更新;而後use- latest-versions能自動幫你將全部依賴升級到最新版本。最後,若是你對所作的更改滿意,則可使用 mvn versions:commit 提交,不滿意的話也可使用 mvn versions:revert 進行撤銷。
POM 表明工程對象模型。它是使用 Maven 工做時的基本組件,是一個 xml 文件。它被放在工程根目錄下,文件命名爲 pom.xml。POM 包含了關於工程和各類配置細節的信息,Maven 使用這些信息構建工程。
構建配置文件是一組配置的集合,用來設置或者覆蓋 Maven 構建的默認配置。使用構建配置文件,能夠爲不一樣的環境定製構建過程,例如 Producation 和 Development 環境。
Profile 在 pom.xml 中使用 activeProfiles / profiles 元素指定,而且能夠用不少方式觸發。Profile 在構建時修改 POM,而且爲變量設置不一樣的目標環境(例如,在開發、測試和產品環境中的數據庫服務器路徑)。
在 Maven 的術語中,倉庫是一個位置(place),例如目錄,能夠存儲全部的工程 jar 文件、library jar 文件、插件或任何其餘的工程指定的文件。
Maven 倉庫有三種類型:
Maven的依賴管理使用的是 Maven - 倉庫 的概念。可是若是在遠程倉庫和中央倉庫中,依賴不能被知足,如何解決呢? Maven 使用外部依賴的概念來解決這個問題。
例如,讓咱們對在 Maven - 建立工程 部分建立的項目作如下修改:
如今你有了本身的工程庫(library),一般狀況下它會包含一些任何倉庫沒法使用,而且 maven 也沒法下載的 jar 文件。若是你的代碼正在使用這個庫,那麼 Maven 的構建過程將會失敗,由於在編譯階段它不能下載或者引用這個庫。
爲了處理這種狀況,須要將這個外部依賴添加到 maven pom.xml 中。
<dependencies>
的第二個 <dependency>
元素 , 闡明瞭外部依賴的關鍵概念。
http://www.oracle.com/technetwork/cn/community/java/apache-maven-getting-started-1-406235-zhs.html
https://maven.apache.org/guides/introduction/introduction-to-the-pom.html
http://www.yiibai.com/maven/enable-proxy-setting-in-maven.html