天天看點

maven生命周期與插件

生命周期 

在有關maven的日常使用中,指令行的輸入往往就對應了生命周期,如mvn package就表示執行預設生命周期階段package. 

生命周期概念 

maven的生命周期就是為了對所有的建構過程進行抽象和統一,這個生命周期包含了項目的清理、初始化、編譯、測試、打包、內建測試、 

驗證、部署和站點生成等幾乎所有建構步驟。即幾乎所有項目的建構,都能映射到這樣一個生命周期上。 

maven的生命周期是抽象的,這意味着生命周期本身不做任何實際的工作,在maven的設計中,實際的任務(如編譯源代碼)都交由插件來完成。 

生命周期抽象了建構的各個步驟,定義了他們的次序,但沒有提供具體實作,maven通過插件機制,每個建構步驟都可以綁定一個或者 

多個插件行為,而且maven為大多數建構步驟編寫并綁定了預設插件。 

maven定義的生命周期和插件機制一方面保證了所有maven項目有一緻的建構标準,另一方面又通過預設插件簡化和穩定了實際項目的建構。 

此外,該機制還提供了足夠的擴充空間,使用者可以通過配置現有插件或者自行編寫插件來自定義建構行為。 

三套生命周期:分别為clean、default、site 

每個生命周期包含一些階段(phase),這些階段是有順序的,并且後面的階段依賴于前面的階段,使用者和maven最直接的互動方式就是調用這些 

生命周期階段。 

較之于生命周期階段的前後依賴關系,三套生命周期本身是互相獨立的,使用者可以僅僅調用clean生命周期的某個階段,或者僅僅調用default 

生命周期的某個階段,而不會對其他生命周期産生任何影響。 

clean生命周期:目的是清理項目,包含pre-clean,clean,post-clean 

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

validate 

initialize 

generate-sources 

process-sources 

generate-resources 

process-resources:處理項目主資源檔案,一般來說是對src/main/resources目錄的内容進行變量替換等工作後,複制到項目輸出的主classpath目錄中 

compile 

process-classes 

generate-test-sources 

process-test-sources 

generate-test-resources 

process-test-resources 

test-compile 

process-test-classes 

test:使用單元測試架構運作測試,測試代碼不會被打包或部署 

prepare-package 

package:接受編譯好的代碼,打包成可釋出的格式,如jar 

pre-integration-test 

integration-test 

post-integration-test 

verify 

install:将包安裝到maven本地倉庫,供本地其他maven項目使用 

deploy:将最終的包複制到遠端倉庫,供其他開發人員和maven項目使用 

site生命周期:目的是建立和釋出項目站點,maven能夠基于pom所包含的資訊,自動生成一個友好的站點 

友善團隊交流和釋出項目資訊,包含如下階段 

pre-site 

site 

post-site 

site-deploy:将生成的項目站點釋出到伺服器上。 

指令執行與生命周期 

$mvn clean:該指令調用clean生命周期的clean階段。實際執行的階段為clean生命周期的pre-clean和clean 

$mvn test:該指令調用default生命周期的test階段。實際執行的階段為default生命周期的validate、initialize等, 

直到test的所有階段 

$mvn clean deploy site-deploy:該指令調用clean生成周期的clean階段、default生成周期的deploy階段,以及site生命 

周期的site-deploy階段。實際執行的階段為clean生命周期的pre-clean,clean階段,default生命周期的所有階段, 

以及site生命周期的所有階段。 

插件綁定: 

maven的生命周期與插件互相綁定,用以完成實際的建構任務,具體而言,是生命周期的階段與插件的目标互相綁定,以完成某個具體的 

建構任務 

如dependency:analyze,dependency:tree,dependency:list,冒号後面是插件maven-dependency-plugin的目标, 

compiler:compile, surefire:test 

default生命周期的階段與插件目标的綁定關系是由項目打包類型決定,打包類型是通過pom中的packaging元素定義的。 

除了内置綁定外,還可以自定義綁定,使用者還能夠自己選擇将某個插件目标綁定到生命周期的某個階段上。如建立項目的源代碼jar包 

<plugin> 

<groupid>org.apache.maven.plugins</groupid> 

<artifactid>maven-source-plugin</artifactid> 

<version>2.2.1</version> 

<executions> 

<execution> 

<id>attach-sources</id> 

<phase>compile</phase> 

<goals> 

<goal>jar-no-fork</goal> 

</goals> 

</execution> 

</executions> 

</plugin> 

phase元素是可選的,因為有很多插件的目标在編寫時已經定義了預設綁定階段,可以使用maven-help-plugin檢視插件詳細資訊,了解插件 

目标的預設綁定階段。 

運作指令如下: 

$mvn help:describe -dplugin=org.apache.maven.plugins:maven-source-plugin:2.2.1 

$mvn help:describe -dplugin=org.apache.maven.plugins:maven-compiler-plugin:2.3.2 

檢視maven-surefire-plugin插件test目标的詳細介紹 

mvn surefire:help -ddetail=true -dgoal=test 

當插件目标被綁定到不同的生命周期階段的時候,其執行順序會由生命周期階段的先後順序決定 

如果多個目标被綁定到同一個階段,這些插件聲明的先後順序決定了目标的執行順序 

插件配置 

使用者可以配置插件目标的參數,進一步調整插件目标所執行的任務,以滿足項目的需求 

指令行插件配置: 

maven-surefire-plugin提供了一個maven.test.skip的參數,當其值為true的時候,就會跳過執行測試。 

mvn package -dmaven.test.skip=true 

參數-d是java自帶的,其功能是通過指令設定一個java系統屬性,maven簡單地重用了該參數,在準備參數 

的時候檢查系統屬性,便實作了插件參數的配置 

pom中插件全局配置(為插件配置全局參數) 

并不是所有的插件參數都适合從指令行配置,有些參數的值從項目建立到項目釋出都不會改變,或者說很少改變, 

對于這種情況,在pom檔案中一次性配置就顯然比重複在指令行輸入要友善。 

使用者可以在聲明插件的時候,對此插件進行一個全局的配置,即所有該基于該插件目标的任務,都會使用這些配置。 

如通常會需要配置maven-compiler-plugin告訴它編譯java1.6版本的源檔案,生成與jvm1.6相容的位元組碼檔案。 

<artifactid>maven-compiler-plugin</artifactid> 

<version>2.1</version> 

<configuration> 

<source>1.6</source> 

<target>1.6</target> 

</configuration> 

pom中插件任務配置:為某個插件任務配置特定的參數 

如maven-antrun-plugin,它有一個目标run,可以用來在maven中調用ant任務。 

擷取插件資訊 

因為大部分插件完善的文檔,是以使用正确的插件并進行正确的配置,并不是一件容易的事 

基本上所有主要的maven插件都來自apache和codehaus 

除了apache上的官方插件之外,托管于codehaus上的mojo項目也提供了大量的maven插件 

http://maven.apache.org/plugins/index.html 

http://repo.maven.apache.org/maven2/org/apache/maven/plugins/ 

http://mojo.codehaus.org/plugins.html 

http://repository.codehaus.org/org/codehaus/mojo/  (目前下面無内容) 

注意:這些插件的文檔和可靠性相對較差,在使用時,如果遇到問題,往往隻能自己看源代碼。 

googlecode插件清單: 

http://code.google.com/hosting/search?q=maven+plugin+label%3amaven&projectsearch=search+project 

不加版本資訊,是讓maven自動擷取最新版本來進行表述: 

mvn help:describe -dplugin=compiler 

mvn help:describe -dplugin=compiler -ddetail=true 

mvn help:describe -dplugin=compiler -dgoal=compile 

從指令行調用插件 

usage: mvn [options] [<goal(s)>] [<phase(s)>] 

options 表示可用的選項 

除了選項之外,mvn指令後面可以添加一個或者多個goal和phase,它們分别是指插件目标和生命周期階段 

可以通過mvn指令激活生命周期階段,進而執行那些綁定在生命周期階段上的插件目标, 

還支援直接從指令行調用插件目标,因為有些任務不适合綁定在生命周期上, 

如maven-help-plugin:describe :不需要在建構項目的時候去描述插件資訊 

 maven-dependency-plugin:tree:不需要在建構項目的時候去顯示依賴樹 

因為這些插件目标應該通過如下方式使用 

mvn dependency:tree 

mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:describe -dplugin=compiler 

這種方式是通過插件字首實作的(否則要寫全groupid、artifactid、version),有了插件字首,maven就能找到對應的artifactid 

插件解析機制 

為了友善使用者使用和配置插件,maven不需要使用者提供完整的插件坐标資訊,就可以解析得到正确的插件。 

插件倉庫 

插件同樣基本坐标存儲在maven倉庫中。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> 

 1:插件從來不從遠端倉庫檢查更新 

 2:插件的預設groupid為org.apache.maven.plugins,如果是maven的官方插件,則可以省略groupid配置 

 解析插件版本: 

 1:maven在超級pom中為所有核心插件設定了版本,超級pom是所有maven項目的父pom,所有項目都繼承這個 

超級pom的配置 

 2:如果使用某個插件沒有設定版本,而此插件又不屬于核心插件的範疇,maven就會檢查最新的release版本 

 3:解析插件字首:插件字首與groupid:artifactid是一一對應的,這種比對關系存儲在倉庫中繼資料中。 

這裡的倉庫中繼資料為groupid/maven-metadata.xml 

http://repo1.maven.org/maven2/org/apache/maven/plugins/maven-metadata.xml