Maven

Maven簡介

Maven是什麼

Maven是Apache組織的開源項目,Maven是一個跨平臺項目管理工具,Maven主要服務於基於Java平臺的項目構建依賴管理項目信息管理。html

什麼是構建(build)

構建(build)包括編譯運行單元測試生成文檔打包部署等繁瑣而不起眼的工做。將構建自動化可以大大節省時間。java

Maven是優秀的構建工具

  1. Maven是一個功能強大的構建工具,它能幫咱們自動化構建過程,用於清理編譯測試生成報告再到打包部署
  2. Maven最大化消除了構建的重複,抽象了一個完整的構建生命週期模型,而且爲絕大部分的構建任務提供了已實現的插件,能夠標準化構建過程,使用Maven構建後,全部項目的構建命令都是簡單一致的,極大的下降了學習升本,有利於項目團隊的標準化。
  3. Maven跨平臺,Windows/Linux/MacOS

總之,Maven不只能幫咱們自動化構建,還能抽象構建過程提供構建任務實現跨平臺對外提供了一致的操做接口。sql

Maven是優秀的依賴管理和項目信息管理工具

  1. Maven提供中央倉庫,幫助咱們自動下載構建
  2. Maven經過一個座標系統準確地定位每個構建(artfact),經過一組座標可以找到任何一個Java類庫文件。
  3. Maven對於項目目錄結構、測試用例命名方式都有既定的規則,只要遵循這些規則,用戶在項目間切換免去了額外的學習升本。約定優於配置

座標與依賴

座標

先看一組座標:設計模式

<modelVersion>4.0.0</modelVersion>
    <groupId>com.eric</groupId>
    <artifactId>eric-parent</artifactId>
    <version>2.0-SNAPSHOT</version>
    <packaging>jar</packaging>
  1. groupId:定義當前Maven項目隸屬的實際項目。
  2. artifactId:定義實際項目中的一個Maven項目(模塊)。推薦使用實際項目名稱做爲artifactId的前綴。
  3. version:定義Maven項目當前所處的版本。
  4. packageing:定義Maven項目的打包方式。不填寫默認是jar
  5. classifier:該元素用來幫助定義構建輸出的一些附屬構建。附屬構建與主構件對應。上例子中主構件是eric-parent-2.0-SNAPSHOT.jar。項目有可能會經過使用一些插件生成如eric-parent-2.0-SNAPSHOT-javadoc.jar、eric-parent-2.0-SNAPSHOT-sources/.jar這樣一些附屬構建,其中包含了Java文檔與源代碼。這個時候,javadoc和sources就是這兩個附屬構建的classifier。這樣,附屬構建也有了本身的惟一座標。注意:不能直接定義項目的classifier,由於附屬構件不是項目直接默認生成的,而是由附加的插件幫助生成的。

依賴

先看一組依賴:api

<dependency>
	<groupId>javax.servlet.jsp</groupId>
    <artifactId>javax.servlet.jsp-api</artifactId>
    <version>2.3.1</version>
    <scope>provided</scope>
</dependency>
  1. groupId:定義當前Maven項目隸屬的實際項目。
  2. artifactId:定義實際項目中的一個Maven項目(模塊)。推薦使用實際項目名稱做爲artifactId的前綴。
  3. version:定義Maven項目當前所處的版本。
  4. type:依賴的類型,對應於項目座標定義的packaging。大部分狀況下不須要聲明,默認是jar。
  5. scope:依賴的範圍
  6. optional:標記依賴是否可選
  7. exclusions:排除依賴的傳遞性

scope依賴範圍

依賴範圍用來控制依賴與三種classpath(編譯classpath、測試classpath、運行classpath)的關係。服務器

  1. compile:編譯依賴範圍,默認的依賴範圍,對於編譯、測試、運行三種classpath都有效。jsp

  2. test:測試依賴範圍。只對於測試classpath有效,在編譯主代碼或者運行項目的使用時沒法使用此類依賴。典型的例子是JUnit,只在編譯測試代碼以及運行測試的時候才須要。maven

  3. provided:已提供依賴範圍,對於編譯和測試classpath有效,可是在運行時無效。典型的例子就是servlet-api,編譯和測試項目的時候須要該依賴,可是運行項目的時候,容器提供,就不須要重複引入。ide

  4. runtime:運行時依賴範圍,對於測試和運行classpath有效。可是在編譯主代碼時無效。典型的例子就是JDBC驅動。項目主代碼編譯只須要JDK提供的JDBC接口,只有在執行測試或者運行項目的時候才須要實現上述接口的具體JDBC驅動。工具

  5. 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>
  6. 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

規律:

  1. 當第二直接依賴的範圍是compile時,傳遞性依賴和第一直接依賴一致。
  2. 當第二直接依賴的範圍是test時,依賴不會傳遞。
  3. 當第二直接依賴的範圍是provided的時候,值傳遞第一直接依賴爲provided的依賴
  4. 當第二直接依賴的範圍是runtime時,除了compile變爲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生命週期

clean生命週期目的是清理項目,三個階段:

  1. per-clean:執行一些清理前須要完成的工做。
  2. clean:清理上一次構建生成的文件。
  3. post-clean執行一些清理後須要完成的工做。

default生命週期

default生命週期定義了真正構建時,所須要執行的全部步驟,它是全部生命週期中最核心的部分,default生命週期是最核心的,它包含了構建項目時真正須要執行的全部步驟。

  1. validate
  2. initialize
  3. generate-sources
  4. process-sources
  5. generate-resources
  6. process-resources :處理項目主資源文件。通常是對src/main/resources目錄的內容進行變量替換後,複製到target目錄,準備打包;
  7. compile :編譯項目的源代碼,編譯src/main/resources目錄的內容至項目輸出的主classpath目錄中;
  8. process-classes
  9. generate-test-sources
  10. process-test-sources:處理項目測試資源文件
  11. generate-test-resources
  12. process-test-resources
  13. test-compile :編譯測試源代碼
  14. process-test-classes
  15. test :運行測試代碼,測試代碼不會被打包或部署;
  16. prepare-package
  17. package :打包成jar或者war或其它可發佈的格式;
  18. pre-integration-test
  19. integration-test
  20. post-integration-test
  21. verify
  22. install :將打好的包安裝到本地倉庫,供其餘項目使用;
  23. deploy :將打好的包安裝到遠程倉庫,供其餘項目使用;

site生命週期

site生命週期的目的是創建和發佈項目站點。Maven可以基於POM所包含的信息,自動生成一個友好的站點,方便團隊交流和發佈項目信息。

  1. pre-site
  2. site :生成項目的站點文檔;
  3. post-site
  4. site-deploy :將生成的項目站點發布到服務器上

命令行與生命週期

從命令行執行Maven任務最主要的方式就是調用Maven的生命週期階段。須要注意的是,各個生命週期是相互獨立的,而一個生命週期的階段是後先後依賴關係的。

  • mvn clean : clean生命週期的clean階段,執行clean生命週期的pre-clean和clean階段。
  • mvn test:該命令調用default生命週期的test階段。實際執行的階段爲default生命週期的validate、initialize等,直到test的全部階段,這解釋了爲何在執行測試的時候,項目代碼可以自動得以編譯。
  • mvn clean install: 實際執行clean生命週期的pre-clean和clean以及default生命週期的validate到install全部階段。結合兩個生命週期,在執行真正的項目構建以前清理項目是一個很好的實踐。
  • mvn clean deploy site-deploy: clean生命週期的pre-clean和clean,default生命週期的全部階段,以及site生命週期的全部階段。

聚合與繼承

Maven學習總結(五)——聚合與繼承

反應堆

在一個多模塊的Maven項目中,反應堆(Reactor)是指全部模塊組成的一個構建結構,對於單模塊項目,反應堆就是該模塊自己,對於多模塊項目來講,反應堆就包含了各模塊之間的依賴於繼承關係,從而可以自動計算出合理的模塊構建順序。

構建順序,無依賴的按pom的讀取順序;有依賴的優先構建較深層次的依賴。

裁剪反應堆,用戶僅僅構建完整反應堆中的某些個模塊,即實時地裁剪反應堆

如何解決Maven依賴衝突

Maven類包衝突終極解決方案

相關文章
相關標籤/搜索