Maven是Apache組織的開源項目,Maven是一個跨平臺項目管理工具,Maven主要服務於基於Java平臺的項目構建、依賴管理、項目信息管理。html
構建(build)包括編譯、運行單元測試、生成文檔、打包和部署等繁瑣而不起眼的工做。將構建自動化可以大大節省時間。java
總之,Maven不只能幫咱們自動化構建,還能抽象構建過程,提供構建任務實現,跨平臺對外提供了一致的操做接口。sql
先看一組座標:設計模式
<modelVersion>4.0.0</modelVersion> <groupId>com.eric</groupId> <artifactId>eric-parent</artifactId> <version>2.0-SNAPSHOT</version> <packaging>jar</packaging>
先看一組依賴:api
<dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.1</version> <scope>provided</scope> </dependency>
依賴範圍用來控制依賴與三種classpath(編譯classpath、測試classpath、運行classpath)的關係。服務器
compile:編譯依賴範圍,默認的依賴範圍,對於編譯、測試、運行三種classpath都有效。jsp
test:測試依賴範圍。只對於測試classpath有效,在編譯主代碼或者運行項目的使用時沒法使用此類依賴。典型的例子是JUnit,只在編譯測試代碼以及運行測試的時候才須要。maven
provided:已提供依賴範圍,對於編譯和測試classpath有效,可是在運行時無效。典型的例子就是servlet-api,編譯和測試項目的時候須要該依賴,可是運行項目的時候,容器提供,就不須要重複引入。ide
runtime:運行時依賴範圍,對於測試和運行classpath有效。可是在編譯主代碼時無效。典型的例子就是JDBC驅動。項目主代碼編譯只須要JDK提供的JDBC接口,只有在執行測試或者運行項目的時候才須要實現上述接口的具體JDBC驅動。工具
system:系統依賴範圍。和provided依賴範圍一致,可是使用system必須經過systemPath元素顯式地指定依賴文件的路徑。因爲此類依賴不是經過Maven倉庫解析的,並且與本機系統綁定,可能形成構建的不可移植。
<dependency> <groupId>javax.sql</groupId> <artifactId>jdbc-stdext</artifactId> <version>2.0</version> <scope>system</scope> <systemPath>${java.home}/lib/rt.jar</systemPath> </dependency>
import:導入依賴範圍。該依賴範圍不會對三種classPath產生實際影響,參照第八章。
A依賴B,B依賴C,咱們說A對於B是第一直接依賴,B對於C是第二直接依賴,A對於C是傳遞性依賴。
第一直接依賴的範圍和第二直接依賴的範圍決定了傳遞性依賴的範圍。
第二依賴 | compile | test | provided | runtime | |
---|---|---|---|---|---|
第一依賴 | - | - | - | - | - |
compile | - | compile | - | - | runtime |
test | - | test | - | - | test |
provided | - | provided | - | provided | provided |
runtime | - | runtime | - | - | runtime |
規律:
Maven引入的傳遞性依賴機制,一方面大大簡化和方便了依賴聲明,另外一方面,大部分狀況下咱們只須要關心項目的直接依賴是什麼,而不用考慮這些直接依賴會引入什麼傳遞性依賴。但有時候,當傳遞性依賴形成問題的時候,咱們就須要清楚的知道該傳遞性依賴是從哪條依賴路徑引入的。
例如,項目A有這樣的依賴關係:A->B->C->X(1.0)、A->D->X(2.0),X是A的傳遞性依賴,可是兩條依賴路徑上有兩個版本的X,那麼哪一個X會被Maven解析使用呢?兩個版本都解析顯然是不對的,由於會形成重複依賴,所以必須選擇一個。Maven依賴調解的第一原則是:路徑最近者優先,該例中X(1.0)的路徑長度爲3,而X(2.0)的路徑長度爲2,所以X(2.0)會被解析使用。
依賴調節第一原則不能解決全部的問題,若是兩條依賴路徑的長度是同樣的呢?那到底誰被解析使用呢。Maven的依賴調解的第二原則:第一聲明者優先。在依賴路徑相等的狀況下,在POM中依賴聲明的順序決定了誰會先被解析使用,順序在前的先解析使用。
只會對當前項目產生影響,當其餘項目依賴於該項目的時候,這個依賴不會被傳遞。
傳遞性依賴可能會使得當前項目引入不穩定版本,須要手動排除。
將部分依賴的版本進行統一管理,相似JAVA中的常量定義與使用。
去除多餘的依賴,顯示地聲明某些必要的依賴。能夠參考【maven】整理依賴,優化依賴
在Maven的術語中,倉庫是一個位置(place)。Maven倉庫是項目中依賴的第三方庫,這個庫所在的位置叫作倉庫。在Maven中,任何一個依賴、插件或者項目構建的輸出,均可以稱之爲構件。Maven倉庫能幫助咱們管理構件(主要是JAR),它就是放置全部JAR文件(WAR,ZIP,POM等等)的地方。
圖-Maven倉庫分類
中央倉庫是Maven核心自帶的遠程倉庫,它包含了絕大部分開源的構件。私服是另外一種特殊的遠程倉庫,爲了節省帶寬和時間,應該在局域網內架設一個私有的服務器,用其代理全部外部的遠程倉庫,內部項目還能部署到私服上供其它項目使用。Maven根據必定規則(從倉庫解析依賴的機制)從倉庫解析並使用依賴構件。
部署到遠程倉庫,採用命令mvn clean deploy,若是當前版本是快照版本,就會部署到快照倉庫,若是當前版本是發行版本,就會部署到發佈版本倉庫。當項目通過完善的測試後須要發佈的時候,就應該將快照版本更改成發佈版本。快照版本只應該在組織內部的項目或者模塊間依賴使用,由於這時,組織對於這些快照的依賴具備徹底理解以及控制權。項目不該該依賴任何組織外部的快照版本,由於不穩定。
Maven的生命週期就是爲了對全部的構建過程進行抽象和統一,Maven從大量項目和構建工具中學習和反思,總結了一套高度完善的、易擴展的生命週期,這個生命週期包含了項目的清理、初始化、編譯、測試、打包、集成測試、驗證、部署和站點生成等幾乎全部的構建步驟。也就是說,幾乎全部的項目構建,都能映射到這樣一個生命週期上。
生命週期是抽象的,實際的任務都由相應的插件來完成,相似模板方法的設計模式。Maven定義的生命週期和插件機制一方面保證了全部Maven項目有一致的構建標準,另外一方面又經過默認插件簡化和穩定了實際項目的構建。此外插件還提供了足夠的擴展空間,用戶能夠經過配置現有插件或者自行編寫插件來自定義構建行爲。
Maven有三套相互獨立的生命週期,分別是clean、default和site。clean生命週期的目的是清理項目,default生命週期的目的是構建項目,而site生命週期的目的是創建項目站點。
clean生命週期目的是清理項目,三個階段:
default生命週期定義了真正構建時,所須要執行的全部步驟,它是全部生命週期中最核心的部分,default生命週期是最核心的,它包含了構建項目時真正須要執行的全部步驟。
site生命週期的目的是創建和發佈項目站點。Maven可以基於POM所包含的信息,自動生成一個友好的站點,方便團隊交流和發佈項目信息。
從命令行執行Maven任務最主要的方式就是調用Maven的生命週期階段。須要注意的是,各個生命週期是相互獨立的,而一個生命週期的階段是後先後依賴關係的。
在一個多模塊的Maven項目中,反應堆(Reactor)是指全部模塊組成的一個構建結構,對於單模塊項目,反應堆就是該模塊自己,對於多模塊項目來講,反應堆就包含了各模塊之間的依賴於繼承關係,從而可以自動計算出合理的模塊構建順序。
構建順序,無依賴的按pom的讀取順序;有依賴的優先構建較深層次的依賴。
裁剪反應堆,用戶僅僅構建完整反應堆中的某些個模塊,即實時地裁剪反應堆。