Maven生命周期
之前我們在指令行中使用的第二個指令是:mvn package。這裡的package是一個maven的生命周期階段
(lifecycle phase )。生命周期指項目的建構過程,它包含了一系列的有序的階段 (phase),而一個階段就是建構過程
中的一個步驟。
一個完整的項目建構過程通常包括清理、編譯、測試、打包、內建測試、驗證、部署等步驟,Maven從中抽取了
一套完善的、易擴充的生命周期。Maven的生命周期是抽象的,其中的具體任務都交由插件來完成。Maven為大多
數建構任務編寫并綁定了預設的插件,如針對編譯的插件:maven-compiler-plugin。使用者也可自行配置或編寫插
件。
那麼生命周期階段和上面說的插件目标之間是什麼關系呢?插件目标可以綁定到生命周期階段上。一個生命周期
階段可以綁定多個插件目标。當maven在建構過程中逐漸的通過每個階段時,會執行該階段所有的插件目标。
maven能支援不同的生命周期,但是最常用的是預設的Maven生命周期 (default Maven lifecycle )。Maven定
義了三套生命周期:clean、default、site,每個生命周期都包含了一些階段(phase)。三套生命周期互相獨立,但
各個生命周期中的phase卻是有順序的,且後面的phase依賴于前面的phase。執行某個phase時,其前面的phase會
依順序執行,但不會觸發另外兩套生命周期中的任何phase。
clean生命周期
clean生命周期主要的目的是清理項目,包括以下三個階段:
1.pre-clean :執行清理前的工作;
2.clean :清理上一次建構生成的所有檔案;
3.post-clean :執行清理後的工作
default生命周期
default生命周期是最核心的,它包含了建構項目時真正需要執行的所有步驟:
1.validate
2.initialize
3.generate-sources
4.process-sources :處理項目主資源檔案。一般來說,是對src/main/resources目錄的内容進行變量替換等
工作後,複制到項目輸出的主classpath目錄中
5.generate-resources
6.process-resources :複制和處理資源檔案到target目錄,準備打包;
7.compile :編譯項目的源代碼,一般來說,是編譯src/main/Java目錄下的Java檔案至項目輸出的主
classpath目錄中;
8.process-classes
9.generate-test-sources
10.process-test-sources :處理項目測試資源檔案。一般來說,是對src/test/resources目錄的内容進行變量
替換等工作後,複制到項目輸出的測試classpath目錄中;
11.generate-test-resources
12.process-test-resources
13.test-compile :編譯項目的測試代碼,一般來說,是編譯src/test/java目錄下的Java檔案至項目輸出的測
試classpath目錄中;
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 :将包安裝到Maven本地倉庫,供本地其他Maven項目使用
23.deploy :将最終的包複制到遠端倉庫,供其他開發人員和Maven項目使用
site生命周期
site生命周期是建立和釋出項目站點,Maven能夠基于POM所包含的資訊,自動生成站點。它包含四個階段:
1.pre-site :在生成項目站點前要完成的工作;
2.site :生成項目的站點文檔;
3.post-site :在生成項目站點後要完成的工作;
4.site-deploy :釋出生成的站點文檔;
Maven的生命周期的各個階段是前後階段互相依賴的,當使用者調用clean的時候,pre-clean 和 clean階段會順序
執行,不會碰觸default的任何階段。
在指令行中的複雜調用和生命周期各個階段的執行情況,從三個例子來說明:
mvn test
該指令調用default生命周期的test階段。實際執行的階段為default生命周期的validate到test的所有階段。
mvn clean install
該指令調用clean生命周期的clean階段和default生命周期的install階段。實際執行的是clean生命周期的pre-
clean、clean階段和default生命周期的validate到install的所有階段。該指令結合了兩個生命周期,是執行真正項目
建構之前清理項目的一個很好的實踐。
mvn clean deploy site-deploy : 該指令調用了clean生命周期的clean階段和default生命周期的deploy階段,
以及site生命周期的site-deploy階段。實際執行的是clean生命周期的pre-clean、clean階段和default生命周期的所
有階段,以及site生命周期的所有階段。
Maven的插件
之前我們用了mvn archetype:generate指令來生成一個項目。那麼這裡的 archetype:generate 是什麼意思呢?
archetype是一個插件的名字,generate是目标(goal)的名字。這個指令的意思是告訴maven執行archetype插件的
generate目标。
一個目标是一個工作單元,而插件則是一個或者多個目标的集合。比如說Jar插件,Compiler插件,Surefire插件
等。從看名字就能知道,Jar插件包含建立Jar檔案的目标, Compiler插件包含編譯源代碼和單元測試代碼的目标。
Surefire插件的話,則是運作單元測試。
看到這裡,估計你能明白了,mvn本身不會做太多的事情,它不知道怎麼樣編譯或者怎麼樣打包。它把建構的任
務交給插件去做。插件定義了常用的建構邏輯,能夠被重複利用。這樣做的好處是,一旦插件有了更新,那麼所有的
maven使用者都能得到更新。
Maven的核心分發包隻有不到3MB的大小,Maven會在需要的時候下載下傳并使用插件,對于插件本身,為了能夠
複用代碼,它往往能夠完成多個任務。Maven的生命周期與插件互相綁定,用以完成實際的建構任務。具體而言是生
命周期的階段與插件的目标互相綁定,以完成某個具體的建構任務。
Maven的核心檔案很小,主要的任務都是由插件來完成。定位到:%本地倉庫%\org\apache\maven\plugins,
可以看到一些下載下傳好的插件:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiclRnblN0LclHdpZXYyd2LcBzNvwVZ2x2bzNXak9CX90TQNNkRrFlQKBTSvwFbslmZvwFMwQzLcVmepNHdu9mZvwFVywUNMZTY18CX052bm9CX90zZNVzaU1UdGdVYzpEWaZXUYpVd1kmYr50MZV3YyI2cKJDT29GRjBjUIF2LcRHelR3LcJzLctmch1mclRXY39DN3QjMxUjM4ETOyITM2EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
Maven官網上有更詳細的官方插件清單:
檢視更多的插件參考:http://maven.apache.org/plugins/index.html
内置綁定
Maven在核心為一些主要的生命周期階段綁定了很多插件的目标。
clean生命周期階段與插件目标的綁定關系:
default生命周期與内置插件綁定關系及具體任務(打包類型: jar):
site生命周期階段與插件目标的綁定關系:
自定義綁定
使用者可以根據需要将任何插件目标綁定到任何生命周期的階段,如:将maven-source-plugin的jar-no-fork目
标綁定到default生命周期的package階段,這樣,以後在執行mvn package指令打包項目時,在package階段之後
會執行源代碼打包,生成如:hi-0.0.1-SNAPSHOT-sources.jar形式的源碼包。
建立的hi項目:
我們在hi項目中的pom.xml配置檔案中加入如下代碼:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
我們右擊項目名字,選擇Run As,再次選擇Maven Build選項
在出現的視窗中的Goals處的輸入框中輸入:package,最後點選Run
控制台輸出成功的是:
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building hi 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ hi ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory E:\Java\JavaEE\Demo\hi\src\main\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ hi ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to E:\Java\JavaEE\Demo\hi\target\classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ hi ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory E:\Java\JavaEE\Demo\hi\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ hi ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to E:\Java\JavaEE\Demo\hi\target\test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ hi ---
[INFO] Surefire report directory: E:\Java\JavaEE\Demo\hi\target\surefire-reports
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running com.imooc.hi.hi.AppTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.054 sec
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ hi ---
[INFO] Building jar: E:\Java\JavaEE\Demo\hi\target\hi-0.0.1-SNAPSHOT.jar
[INFO]
[INFO] --- maven-source-plugin:2.4:jar-no-fork (default) @ hi ---
[INFO] Building jar: E:\Java\JavaEE\Demo\hi\target\hi-0.0.1-SNAPSHOT-sources.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 7.598 s
[INFO] Finished at: 2016-12-29T18:33:54+08:00
[INFO] Final Memory: 16M/129M
[INFO] ------------------------------------------------------------------------
我們看看項目hi下的變化:
配置插件
定義解釋:插件目标
Maven插件高度易擴充,可以友善的進行自定義配置。當我們了解了maven插件之後,我們發現如果為每一個功
能編寫一個獨立的插件顯然是不可取的,因為這些任務背後有很多可以複用的代碼,是以,把這些功能聚集在一個插
件裡,每一個功能我們就稱之為一個插件目标。
舉個例子:
maven-dependency-plugin有十多個目标,每個目标對應了一個功能
分析項目依賴:dependency:analyze
列出項目依賴樹:dependency: tree
列出項目所有已解析的依賴:dependency:list
POM中插件全局配置
有些參數的值從項目的建立到項目釋出都不會改變,或者說很少改變,對于這種情況,就可以在pom.xml中進行
全局配置。
例如:配置maven-compiler-plugin插件編譯源代碼的JDK版本為1.8:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.4</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
這樣,不管綁定到compile階段的maven-compiler-plugin: compile 還是綁定到test-compiler 階段的maven-
compiler-plugin: testCompiler 任務,就都能夠使用該配置,基于JavaSE1.8版本進行編譯。
插件倉庫
跟其他構件一樣,插件也是根據坐标存儲在Maven倉庫中。超級POM中Maven配置的預設插件遠端倉庫如下:
<pluginRepositories>
<pluginRepository>
<id>central</id>
<name>Central Repository</name>
<url>http://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
<releases>
<updatePolicy>never</updatePolicy>
</releases>
</pluginRepository>
</pluginRepositories>
Maven生命周期和插件就說到這裡。