天天看點

Maven實戰(Maven In Action)

第1章 Maven簡介

  • 自Maven 2.0.9開始,所有核心的插件都設定了穩定版本,這意味着日常使用Maven時幾乎不會受到不穩定插件的影響。此外,Maven社群也提倡為你使用的任何插件設定穩定的版本。從Maven 3開始,如果你使用插件時未設定版本,會看到警告資訊。 P8

第2章 Maven的安裝和配置

  • 新的環境變量配置需要新的cmd視窗才能生效

第3章 Maven使用入門

  • POM(Project Object Model,項目對象模型)

    定義了項目的基本資訊,用于描述項目如何建構,聲明項目依賴等等。

  • modelVersion指定了目前POM模型的版本,對應Maven 2及Maven 3來說,它隻能是4.0.0
  • SNAPSHOT意為快照,說明該項目還處于開發中,是不穩定的版本。
  • test依賴範圍表示該依賴隻對測試有效,隻能在測試代碼中引用,不能在主代碼中引用。如果不聲明依賴範圍,預設值是compile,表示該依賴對主代碼和測試代碼都有效。
  • finalName可以自定義打封包件的名稱,詳見第14章。

第5章 坐标和依賴

  • 當pom中不定義packaging時,Maven會使用預設值jar。
  • packaging并非一定與構件的擴充名對應,比如packaging為maven-plugin的構件擴充名為jar。
  • 依賴範圍就是用來控制依賴與三種classpath(編譯classpath、測試classpath、運作classpath)的關系。
    • compile:編譯依賴範圍。如果沒有指定,就會預設使用該依賴範圍。使用此依賴範圍的Maven依賴,對應編譯、測試、運作三種classpath都有效。
    • test:測試依賴範圍。使用此依賴範圍的Maven依賴,隻對于測試classpath有效,在編譯主代碼或者運作項目時将無法使用此類依賴。
    • provided:已提供依賴範圍。使用此依賴範圍的Maven依賴,對于編譯和測試classpath有效,但在運作時無效。
    • runtime:運作時依賴範圍。使用此依賴範圍的Maven依賴,對于測試和運作classpath有效,但在編譯主代碼時無效。
    • system:系統依賴範圍。該依賴範圍與三種classpath的關系,和provided依賴範圍完全一緻。但是,使用system範圍的依賴時必須通過systemPath元素顯示地指定依賴檔案的路徑。由于此類依賴不是通過Maven倉庫解析的,而且往往與本機系統綁定,可能造成建構的不可移植,是以應該謹慎使用。systemPath元素可以引用環境變量,如:

      ${java.home}

    • import(Maven 2.0.9及以上):導入依賴範圍。該依賴範圍不會對三種classpath産生實際的影響。隻在dependencyManagement元素下才有效果,使用該依賴範圍的依賴通常指向一個POM,作用是将目标POM中的dependencyManagement配置導入并合并到目前POM的dependencyManagement元素中。P134
  • 除import以外的各種依賴範圍與三種classpath的關系如下表所示:
依賴範圍(scope) 對于編譯classpath有效 對于測試classpath有效 對于運作時classpath有效 例子
compile Y Y Y spring-core
test - Y - JUnit
provided Y Y - servlet-api
runtime - Y Y JDBC驅動實作
system Y Y - 本地的,Maven倉庫之外的類庫檔案
  • 傳遞性依賴:Maven會解析各個直接依賴的POM,将那些必要的間接依賴以傳遞性依賴的形式引入到目前項目中。
  • 傳遞性依賴範圍,第一清單示第一直接依賴範圍,第一行表示第二直接依賴範圍。規律:當第二直接依賴依賴的範圍是compile時,傳遞性依賴的範圍與第一直接依賴的範圍一緻;當第二直接依賴的範圍是test時,依賴不會得以傳遞;當第二直接依賴的範圍是provided時,隻傳遞第一直接依賴範圍也為provided的依賴,且傳遞性依賴的範圍同樣為provided;當第二直接依賴的範圍是runtime時,傳遞性依賴的範圍與第一直接依賴的範圍一緻,當compile例外,此時傳遞性依賴的範圍為runtime。

    參考:http://seanzhou.iteye.com/blog/1688740

compile test provided runtime
compile compile - - runtime
test test - - test
provided provided - provided provided
runtime runtime - - runtime
  • 依賴調解

    從Maven 2.0.9開始,為了盡可能避免建構的不确定性,Maven定義了依賴調解的第二原則:第一聲明者優先。在依賴路徑長度相等的前提下,在POM中依賴聲明的順序決定了誰會被解析使用,順序最靠前的那個依賴優勝。第一原則:路徑最近者優先。

  • 可選依賴不被傳遞
  • 排除依賴
  • 歸類依賴,使用Maven屬性
  • 優化依賴

    mvn dependency:list

    ,檢視已解析依賴清單

    mvn dependency:tree

    ,檢視已解析依賴樹

    mvn dependency:analyze

    ,分析目前項目的依賴

    顯示聲明任何項目中直接用到的依賴。

第6章 倉庫

  • 何為Maven倉庫

    得益于坐标機制,任何Maven項目使用任何一個構件的方式都是完全相同的。在此基礎上,Maven可以在某個位置統一存儲所有Maven項目共享的構件,這個統一的位置就是倉庫。為了實作重用,項目建構完畢後生成的構件也可以安裝或者部署到倉庫中,供其他項目使用。

  • 倉庫的分類

    本地倉庫、遠端倉庫(中央倉庫、私服、其他公共庫)

  • 超級POM

    $M2_HOME/lib/maven-model-builder-3.0.jar

    中的org/apache/maven/model/pom-4.0.0.xml
  • 任何一個倉庫聲明的id必須是唯一的,尤其需要注意的是,Maven自帶的中央倉庫使用的id為central,如果其他的倉庫聲明也使用該id,就會覆寫中央倉庫的配置。
  • 遠端倉庫的認證

    倉庫資訊可以直接配置在POM檔案中,但是認證資訊必須配置在settings.xml檔案中。

  • 快照版本
  • 從倉庫解析依賴的機制

    RELEASE和LATEST版本,它們分别對應了倉庫中存在的該構件的最新釋出版本和最新版本(包含快照)。Maven 3不再支援在插件配置中石油LATEST和RELEASE。如果不設定插件版本,其效果就和RELEASE一樣,Maven隻會解析最新的釋出版本構件。

  • 鏡像

    如果倉庫X可以提供倉庫Y存儲的所有内容,那麼就可以認為X是Y的一個鏡像。換句話說,任何一個可以從倉庫Y獲得的構件,都能夠從它的鏡像中擷取。存在的意義:有的POM中指定了倉庫,這樣就可以在攔截去遠端倉庫的請求了。

It works like this: a POM may declare a repository to use in resolving certain artifacts. However, this repository may have problems with heavy traffic at times, so people have mirrored it to several places.

第7章 生命周期和插件

  • Maven的生命周期是抽象的,其實際行為都是由插件來完成。
  • 三套生命周期:clean、default和site
    • clean生命周期

      clean生命周期的目的是清理項目,它包含三個階段:

      Maven實戰(Maven In Action)
    • default生命周期

      default生命周期定義了真正建構時所需要的執行的所有步驟,它是所有生命周期中最核心的部分,其包含的階段如下,隻對重要的階段進行解釋:

      Maven實戰(Maven In Action)
      Maven實戰(Maven In Action)
    • site生命周期

      site生命周期的目的是建立和釋出項目站點,Maven能夠基于POM所包含的資訊,自動生成一個友好的站點,友善團隊交流和釋出項目資訊。該生命周期包含如下階段:

      Maven實戰(Maven In Action)
  • 較之于生命周期階段的前後依賴關系,三套生命周期本身是互相獨立的,使用者可以僅僅調用clean生命周期的某個階段,或者僅僅調用default生命周期的某個階段,而不會對其他生命周期産生任何影響。

    當使用者調用clean生命周期的clean階段的時候,不會觸發default生命周期的任何階段,反之亦然,當使用者調用default生命周期的compile階段的時候,也不會觸發clean生命周期的任何階段。

  • 插件目标:插件功能就是一個插件目标。
  • 插件綁定,Maven的生命周期與插件互相綁定,用以完成實際的建構任務。
  • 内置綁定,為了能讓使用者幾乎不用任何配置就能建構Maven項目,Maven在核心為一些主要的生命周期階段綁定了很多插件目标,當使用者通過指令行調用生命周期階段的時候,對應的插件目标就會執行相應的任務。P100
  • 自定義綁定:除了内置綁定以外,使用者還能夠自己選擇将某個插件目标綁定到生命周期的某個階段上,這種自定義綁定方式能讓Maven項目在建構過程中執行更多更富特色的任務。比如:使用

    maven-source-plugin

    建立項目的源碼jar包。
    • 對應自定義綁定的插件,使用者總是應該聲明一個非快照版本,這樣可以避免由于插件版本變化造成的建構不穩定性。
    • 有很多插件的目标在編寫時已經定義了預設綁定階段。
  • 插件配置
    • 指令行插件配置
    • POM中插件全局配置
    • POM中插件任務配置
  • 從指令行調用,目标字首(Goal Prefix)
  • 插件的預設groupId

    在POM中配置插件時,如果該插件是Maven的官方插件(即如果其groupId為

    org.apache.maven.plugin

    ),就可以省略groupId配置。雖然可以省略,但是不建議使用Maven這一機制,這樣的配置會讓團隊不熟悉Maven的同學感到費解。
  • 解析插件版本

    Maven在超級POM中為所有核心插件設定了版本,超級POM是所有Maven項目的父POM,所有項目都繼承這個超級POM的配置。

    Maven 3調整了解析機制,當插件沒有聲明版本時,不再解析至latest,而是使用release。這樣就可以避免由于快照頻繁更新而導緻的插件行為不穩定。

  • 解析插件(目标)字首

    插件字首與groupId:artifactId是一一對應的,這種比對關系存儲在倉庫中繼資料中。

第8章 聚合與繼承

  • 聚合
    • 打包方式packaging的值必須為pom
    • 元素modules是實作聚合的最核心配置
  • 繼承
    • 打包方式packaging的值必須為pom
    • 使用parent元素聲明父子產品
    • 可繼承的POM元素,groupId、version、distributionManagement、properties、dependencies、dependencyManagement、build等
    • Maven提供的dependencyManagement元素既能讓子子產品繼承到父子產品的依賴配置,又能保證子子產品的依賴使用的靈活性。在dependencyManagement元素下的依賴聲明不會引入實際的依賴,不過它能夠限制dependencies下的依賴的使用。
    • 插件管理,pluginManagement元素幫助管理插件。
  • 聚合與繼承的關系

    聚合主要是為了友善快速建構項目,繼承主要是為了消除重複配置。在實際項目中,一個POM即是聚合POM又是父POM。

  • 約定由于配置(Convention Over Configuration)
    • 超級POM說明 P141
  • 反應堆(Reactor)

    在一個多子產品的Maven項目中,反應堆(Reactor)是指所有子產品組成的一個建構結構。對于單子產品的項目,反應堆就是該子產品本身,但對于多子產品項目來說,反應堆就包含了個子產品之間繼承與依賴的關系,進而能夠自動計算出合理的子產品建構順序。

第14章 靈活的建構

  • Maven屬性
    • 通過

      <properties>

      元素使用者可以自定義一個或多個Maven屬性,然後在POM的其他地方使用

      ${屬性名稱}

      的方式引用該屬性,這種做法的最大意義在于消除重複。
    • 内置屬性:主要有兩個常用内置屬性——

      ${basedir}

      表示項目的跟目錄,即包含pom.xml檔案的目錄;

      ${version}

      表示項目版本。
    • POM屬性:使用者可以使用該類屬性引用POM檔案中對應元素的值。例如

      ${project.artifactId}

      就對應了

      <project><artifactId>

      元素的值,常用的POM屬性如下圖所示,這些屬性都對應了一個POM元素,他們中的一些屬性的預設值都是在超級POM中定義的。
      Maven實戰(Maven In Action)
    • 自定義屬性:使用者可以在POM的

      <property>

      元素下自定義Maven屬性。例如:
      Maven實戰(Maven In Action)
      然後在POM中其他地方使用

      ${my.prop}

      時被替換成hello。
    • Settings屬性:與POM屬性同理,使用者使用以

      settings.

      開頭的屬性引用

      settings.xml

      檔案中XML元素的值,如常用的

      ${settings.localRepository}

      指向使用者本地倉庫的位址。
    • Java系統屬性:所有Java系統屬性都可以使用Maven屬性引用,例如

      ${user.home}

      指向了使用者目錄。可以使用

      mvn help:system

      檢視所有的Java系統屬性。
    • 環境變量屬性:所有環境變量都可以使用以

      env.

      開頭的Maven屬性引用。例如

      ${env.JAVA_HOME}

      指代了JAVA_HOME環境變量的值。可以使用

      mvn help:system

      檢視所有的環境變量。
  • 建構環境的差異
  • 資源過濾
  • Maven Profile