除了座標、依賴以及倉庫以外,Maven另外兩個核心概念是生命週期和插件。命令行的輸入每每對應生命週期,而生命週期是抽象的,實際行爲由插件完成。html
在Maven出現以前,項目構建的生命週期就已經存在,清理、編譯、測試及部署。但公司與公司間,項目與項目間,每每使用不一樣方式作相似的工做。
Maven的生命週期對全部的構建過程進行抽象和統一。這個生命週期包括項目的清理、初始化、編譯、測試、打包、集成測試、驗證、部署和站點生成等幾乎全部構建步驟。
Maven的生命週期是抽象的,實際任務都交由插件來完成。這種思想與設計模式中的模板方法(Template Method)很是類似,生命週期是模板方法,而插件就是子類覆寫的方法。apache
總結:Maven的生命週期定義了項目構建的流程,而插件負責實現流程中每一個步驟,最後將插件與生命週期流程中每一個步驟綁定便可完成項目構建。在這個過程當中插件能夠在多個項目中複用,而經過更換插件綁定亦可實現差別化構建。設計模式
Maven擁有三套相互獨立的生命週期。服務器
生命週期 | 階段(phase) | 說明 |
---|---|---|
clean | pre-clean | 執行清理前須要完成的工做 |
clean | 清理上一次構建生成的文件 | |
post-clean | 執行清理後須要完成的工做 | |
default | vaildate | 驗證,確保當前配置和POM內容是有效的,包含對POM文件樹的驗證。 |
intianlize | 初始化,執行構建生命週期的主任務以前的初始化 | |
generate-sources | 生成源碼,代碼生成器生成後期階段中處理或編譯的源代碼 | |
proccess-sources | 處理源碼,提供解析、修改和轉換源碼。常規源碼和生成的源碼均可以再這裏處理 | |
generate-resoureces | 生成資源,生成非源碼資源,一般包括元數據文件和配置文件 | |
process-resources | 處理資源,處理非源碼資源,修改、轉換和重定位資源都能在這階段發生 | |
compile | 編譯,編譯源碼。編譯過的類被放到目標目錄樹中 | |
process-classes | 處理類,處理類文件轉換和加強步驟。字節碼交織器和經常使用工具常在這一階段操做 | |
generate-test-sources | 生成測試源碼,生成要操做的單元測試代碼 | |
process-test-sources | 處理測試源碼,在編譯前對測試源碼執行任何須要的處理。修改、轉換或複製源代碼 | |
generate-test-resources | 生成測試資源,生成與測試相關的非源碼資源 | |
process-test-resources | 處理測試資源,處理、轉換或從新定位於測試相關的資源 | |
test-compile | 測試編譯,編譯單元測試的源碼 | |
process-test-classes | 處理測試類,對編譯生成文件作後期處理(Maven2.0.5及以上) | |
test | 測試,運行編譯過的單元測試並累計結果 | |
prepare-package | 執行打包前的全部操做(Maven2.1及以上) | |
package | 打包,將可執行的二進制文件打包到一個分佈式歸檔文件中,如jar或war | |
pre-integration-test | 前集成測試,準備集成測試,將歸檔文件部署到一個服務器上執行 | |
integration-test | 集成測試,執行真正的集成測試,指在一個受到必定控制的模擬的真實部署環境中測試代碼 | |
post-integration-test | 後集成測試,解除集成測試準備,涉及環境重置或從新初始化 | |
verify | 檢驗,檢驗可部署歸檔文件的有效性和完整性,經過後,將安裝該歸檔 | |
install | 安裝,將項目包安裝到本地倉庫,供其餘項目依賴 | |
deploy | 部署,將項目發佈到遠程倉庫,供其餘開發人員與項目共享 | |
site | pre-site | 執行一些在生成項目站點以前須要完成的工做 |
site | 生成項目站點文檔 | |
peo-site | 執行一些在生成項目站點以後須要完成的工做 | |
site-deploy | 將生成的項目站點發布到服務器上 |
從命令行執行Maven任務的最主要方式就是調用Maven的生命週期階段。
Ps:Maven的三套生命週期是相互獨立的,而一個生命週期階段是有先後依賴關係的。
如:
mvn clean:該命令調用clean生命週期的clean階段,實際執行clean生命週期中的pre-clean,clean階段
mvn test:該命令調用default生命週期的test階段,實際執行default生命週期中vaildate至test全部階段
mvn clean install:該命令調用clean生命週期的clean階段以及default生命週期的install階段,實際執行clean生命週期中的pre-clean,clean階段,以及default生命週期的vaildate至install全部階段。
mvn clean deploy site-deploy:該命令調用clean生命週期的clean階段、default生命週期的deploy階段以及site生命週期的site-deploy階段,實際執行實際執行clean生命週期中的pre-clean,clean階段、default生命週期的全部階段以及site生命週期的全部階段。
因爲Maven中主要生命週期階段很少,而經常使用Maven命令都是基於這些階段簡單組合而成,所以只要對Maven生命週期有基本的理解,就能夠正確而熟練地使用Maven命令。maven
Maven的核心僅定義了抽象的生命週期,具體的任務是交由插件完成,插件以獨立的構件形式存在。
對於插件自己,爲了代碼複用,它每每具有多個功能,而每一個功能都統稱爲插件目標(Plugin Goal)。
如:maven-dependency-plugin,基於項目依賴作不少事情。
1 幫助分析項目依賴,幫助找出潛在的無用依賴;
2 列出項目依賴樹,幫助分析依賴來源
3 列出項目已解析的依賴 等...
這些任務有不少代碼能夠複用。所以,這些功能彙集在一個插件中,每一個功能就是一個插件目標。
插件目標使用語法:
1 完整命令 mvn groupId:artifactId:version:goal 如 mvn org.apache.maven.plugins:maven-dependency-plugin:3.0.2:tree
2 簡化version mvn groupId:artifactId:goal 如 mvn org.apache.maven.plugins:maven-dependency-plugin:tree
3 使用插件前綴 mvn 插件前綴:goal 如 mvn dependency:tree分佈式
Maven的生命週期與插件目標相互綁定,用以完成實際的構建任務。ide
爲了使用戶幾乎不用任何配置就能構建Maven項目,Maven在覈心爲一些主要的生命週期階段綁定了不少插件的目標,
當用戶經過命令行調用生命週期時,對應的插件目標就會執行相應的任務。
以下圖(default生命週期的階段與插件目標的綁定關係由項目打包類型決定(packaging元素)下圖以jar包構建爲例)工具
生命週期 | 階段(phase) | 內置插件 | 執行任務 |
---|---|---|---|
clean | pre-clean | ||
clean | maven-clean-plugin:clean | 刪除項目的輸出目錄 | |
post-clean | |||
default | vaildate | ||
intianlize | |||
generate-sources | |||
proccess-sources | |||
generate-resoureces | |||
process-resources | maven-resources-plugin:resources | 複製主資源文件至主輸出目錄 | |
compile | maven-compiler-plugin:compile | 編譯主代碼至主輸出目錄 | |
process-classes | |||
generate-test-sources | |||
process-test-sources | |||
generate-test-resources | |||
process-test-resources | maven-resources-plugin:testResources | 複製測試資源文件至測試輸出目錄 | |
test-compile | maven-compiler-plugin:testCompile | 編譯測試代碼至測試輸出目錄 | |
process-test-classes | |||
test | maven-surefire-plugin:test | 執行測試用例 | |
prepare-package | |||
package | maven-jar-plugin:jar | 建立項目jar包 | |
pre-integration-test | |||
integration-test | |||
post-integration-test | |||
verify | |||
install | maven-install-plugin:install | 將項目輸出構件安裝到本地倉庫 | |
deploy | maven-deploy-plugin:deploy | 將項目輸出構件安裝到遠程倉庫 | |
site | pre-site | ||
site | maven-site-plugin:site | 生成項目站點 | |
peo-site | |||
site-deploy | maven-site-plugin:deploy | 將項目站點部署到遠程服務器上 |
Ps:空白的生命週期階段,默認沒有綁定任何插件,所以也沒有任何實際行爲
除默認打包類型jar外,常見的打包類型還有war、pom、maven-plugin、ear等。查看相關類型插件綁定官網http://maven.apache.org/guide...post
除了內置綁定之外,用戶能夠選擇將某個插件目標綁定到生命週期的某個階段,能讓Maven項目在構建過程當中執行更多更富特點的任務。
如maven-source-plugin:jar-no-fork,可以將項目主代碼打成jar文件。將其綁定到default生命週期的verify階段上,在執行完繼承測試後和安裝構件以前建立源碼jar包。配置以下單元測試
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> <version>3.0.1</version> <executions> <!-- 插件執行配置 --> <execution> <!-- executions下每一個execution子元素能夠配置執行一個任務 --> <id>attach-sources</id> <!-- 配置任務id --> <!-- <phase>verify</phase> --> <!-- phase元素配置綁定生命週期階段 --> <goals> <!-- 配置要執行的插件目標 --> <goal>jar-no-fork</goal> </goals> <execution> </executions> </plugin> </plugins> </build>
完成自定義插件綁定後,運行mvn verify便可。
在上述代碼中,註釋了phase元素也能實現綁定,緣由是不少插件目標在編寫時已經定義了默認綁定階段,可使用maven-help-plugin查看插件詳細信息,瞭解插件目標的默認綁定階段。
mvn help:describe -Dplugin=groupId:artifactId:version
當插件目標綁定到不一樣的生命週期時,其執行順序會由生命週期階段的前後順序決定。若是多個目標被綁定到同一個階段,這些插件聲明的前後順序決定目標的執行順序。
完成插件目標與生命週期綁定後,用戶還能夠配置插件目標的參數,進一步調整插件目標所執行的任務,以知足項目的需求。幾乎全部Maven插件目標都有一些可配置參數,可經過命令行和POM配置等方式來配置參數。
使用-D參數,並伴隨一個參數名=參數值的形式,來配置參數
(命令行參數是由插件參數的表達式(Expression)決定,並不是全部插件目標參數都有表達式,只能在POM中配置)
如maven-surrfire-plugin插件提供了一個maven.test.skip參數,當其值爲true時,就會跳過執行測試。
mvn install -Dmaven.test.skip=true
並不是全部插件參數都適合從命令行配置,有些參數的值從項目構建到項目發佈都不會改變,或不多改變,在POM文件中一次性配置顯然比重複在命令行輸入要方便。
如mvan-compiler-plugin 能夠配置全局參數 實現compile以及testCompile任務都能使用全局配置。
<build> <plugins> <plugin> <groupId>...</groupId> <artifactId>...</artifactId> <version>...</version> <configuration> <!-- 聲明插件全局配置 全部基於該插件目標的任務,都會使用這些配置 --> ... </configuration> </plugin> </plugins> </builds>
除了爲插件配置全局的參數,還能夠爲某個插件任務配置特定的參數。
如maven-antrun-plugin 能夠配置插件任務參數,使run目標任務在不一樣生命週期輸出不一樣的語句。
<build> <plugins> <plugin> <groupId>...</groupId> <artifactId>...</artifactId> <version>...</version> <executions> <execution> <id>...</id> <phase>...</phase> <goals> <goal>...</goal> </goals> <configuration> <!-- 插件任務一配置 --> ... </configuration> </execution> <execution> <id>...</id> <phase>...</phase> <goals> <goal>...</goal> </goals> <configuration> <!-- 插件任務二配置 --> ... </configuration> </execution> ... </executions> </plugin> </plugins> </builds>
僅僅理解如何配置使用插件是不夠的,實現一個構建任務,用戶需知道去哪找到合適的插件,並詳細瞭解該插件的配置點。因爲Maven的插件很是多,並且這其中大部分沒有完善的文檔,所以使用正確的插件並進行正確的配置,不容易。
基本上全部的Maven插件都來自於apache和Codehaus。
apache | 說明 | 官方插件,用戶多,穩定性好 |
詳細列表 | http://maven.apache.org/plugi... | |
下載地址 | http://repo1.maven.org/maven2... | |
Codehaus | 說明 | 文檔和可靠性相對較差,遇到問題,每每須要本身看源碼 |
詳細列表 | http://mojo.codehaus.org/plug... | |
下載地址 | http://repository.codehaus.or... |
雖然並不是全部插件都提供了完善的文檔,但一些核心插件的文檔仍是很是豐富的。
通常來講,經過閱讀插件在文檔中的使用介紹和實例,就應該可以在本身的項目中很好地使用該插件。
當咱們須要瞭解很是細節的目標參數時,就須要進一步訪問該插件每一個目標的文檔。文檔詳細解釋了該參數的做用、類型等信息。
除了訪問在線的插件文檔以外,還能夠藉助maven-help-plugin來獲取插件的詳細信息。
執行maven-help-plugin的describe目標,指定要查詢的插件的座標,可查詢插件的座標,前綴(Goal Prefix),目標信息
mvn help:describe -Dplugin = (groupId:artifactId[:version] | Goal Prefix) -Dgoal = goal -Ddetail
mvn -h 顯示mvn命令幫助,能夠看到以下信息:
usage:mvn [options] [<goal(s)]>] [<phase(s)>] Options: ...
options表示可用的選項,除了選項以外,mvn命令後面能夠添加一個到多個goal和phase,分別指插件目標和生命週期階段。mvn命令能夠激活生命週期階段,從而執行那些綁定在生命週期階段上的插件目標。也能夠直接執行插件目標,由於有些插件目標不適用於生命週期階段,如maven-help-plugin:describe。
直接執行插件目標語法 在上文中已說起,可在插件目標中查看。
在命令行中執行插件目標,可以使用插件前綴替代座標,方便用戶使用和配置插件。
Maven的這一特性是雙刃劍,雖然它簡化了插件的使用和配置,但若是出現問題,用戶很難定位出問題的插件構件。
如mvn help:system 執行了什麼插件。它的座標是什麼。這與Maven的插件解析機制有關。
與依賴構件同樣,插件構件一樣基於座標存儲在Maven倉庫中,在須要的時候,Maven會先從本地倉庫尋找插件,不存在則從遠程倉庫找到插件,下載到本地倉庫使用。
插件的遠程倉庫不一樣於依賴的遠程倉庫,配置方式也不一樣,插件倉庫配置以下:
<pluginRepositories> <pluginRepository> ... <!-- 此處與依賴遠程倉庫配置同樣,可參考閱讀總結二查看 --> </pluginRepository> ... </pluginRepositoties>
Maven內置了插件倉庫指向中央倉庫,並關閉了對SNAPSHOT的支持。
通常來講,中央倉庫所包含的插件徹底可以知足咱們的須要,所以也不須要配置其餘的插件倉庫,只有在不多的狀況下,項目使用的插件沒法在中央倉庫找到,或者本身編寫了插件,能夠參考上述配置,在POM中或settings.xml中 加入其餘插件倉庫。
在POM中配置插件時,若是該插件是Maven官方插件(groupId爲org.apache.maven.plugins),則能夠省略groupId配置。
不推薦使用這一特性,只省略一行配置,但會讓團隊中不熟悉Maven的成員感到費解。
一樣爲了簡化插件的配置和使用,用戶可沒有提供插件的版本,Maven會自動解析插件版本。
首先,Maven在超級POM中爲全部核心插件設定了版本,超級POM是全部Maven項目的父POM,全部項目都繼承了這個超級POM配置。因此用戶使用插件未設定插件版本的狀況有如下幾種:
1 核心插件:經過超級POM繼承設定版本
2 非核心插件:經過倉庫元數據 groupId/artifactId/maven-metadata.xml ,遍歷並歸併本地倉庫和遠程倉庫的倉庫元數據,根據latest和release計算出插件的版本。Maven3以後使用release,避免使用latest獲取到快照版本,由於快照版本的頻繁更新會致使插件行爲的不穩定。
mvn命令行支持使用插件前綴來簡化插件的調用。Maven是如何經過插件前綴獲取插件的座標的?
插件前綴與groupId:artifactId是一一對應的,這種匹配關係存儲在倉庫元數據中,該倉庫員數據位於groupId/maven-metadate.xml,Maven在解析插件倉庫元數據時,會默認使用org.apache.maven.plugins和org.codehaus.mojo兩個groupId,能夠再settings.xml中配置其餘groupId
<settings> ... <pluginGroups> <pluginGroup>...</pluginGroup> </pluginGroups> ... <settings>
插件倉庫元數據中存儲了全部插件前綴與group:artifactId的對應關係插件倉庫元數據檢查順序爲:apache -> codehaus -> 用戶自定義插件組 -> 都不包含該前綴,則報錯