1. 程式人生 > >Maven:生命週期和外掛。

Maven:生命週期和外掛。

Maven的生命週期與外掛相互繫結,用以完成實際的構建任務。具體而言,是生命週期的階段與外掛的目標相互繫結,以完成某個具體的構建任務。例如專案編譯這一任務,他對應了default生命週期的compile這一階段,而maven-compiler-plugin這一外掛的compile目標能夠完成該任務。因此,將他們繫結,就能實現專案編譯的目的,如下圖所示。

內建繫結

為了能讓使用者幾乎不用任何配置就能構建Maven專案,Maven在核心為一些主要的生命週期階段綁定了很多外掛的目標,當用戶通過命令列呼叫生命週期階段的時候,對應的外掛目標就會執行相應的任務。

clean生命週期僅有pre-clean、clean和post-clean三個階段,其中的clean與maven-clean-plugin:clean繫結。maven-clean-plugin僅有clean這一個目標,其作用就是刪除專案的輸出目錄。

site生命週期有pre-site、site、post-site和site-deploy四個階段,其中,site和maven-site-plugin:site相互繫結,site-deploy和maven-site-plugin:deploy相互繫結。maven-site-plugin有很多目標,其中,site目標用來生成專案站點,deploy目標用來將專案站點部署到遠端伺服器上。

相對於clean和site生命週期來說,default生命週期與外掛目標的繫結就顯得複雜一些。這是因為對於任何專案來說,例如jar專案和war專案,他們的專案清理和站點生成任務是一樣的,不過構建過程會有區別。例如jar專案需要打包JAR包,而war專案需要打成WAR包。

由於專案的打包型別會影響構建的具體過程,因此,default生命週期的階段與外掛目標的繫結關係由專案打包型別所決定,打包型別是通過POM中的packaging元素定義的。最常見、最重要的打包型別是jar,他也是預設的打包型別。基於該打包型別的專案,其default生命週期的內建外掛繫結關係及具體任務如下所示。

生命週期階段 外掛目標 執行任務

process-resources

compile

process-test-resources

test-compile

test

package

install

deploy

 

maven-resources-plugin:resources

maven-compiler-plugin:compile

maven-reousrces-plugin:testResources

maven-compiler-plugin:testCompile

maven-surefire-plugin:test

maven-jar-plugin:jar

maven-install-plugin:install

maven-deploy-plugin:deploy

 

複製主資原始檔至主輸出目錄

編譯主程式碼至主輸出目錄

複製測試資原始檔至測試輸目錄

編譯測試程式碼至測試輸出目錄

執行測試用例

建立專案jar包

將專案輸出構件安裝到本地倉庫

將專案輸出構件部署到遠端倉庫

 

注意,上表只列出了擁有外掛繫結關係的階段,default生命週期還有很多其他階段,預設他們沒有繫結任何外掛,因此也沒有任何實際行動。

除了預設的打包型別jar之外,常見的打包型別還有war、pom、maven-plugin、ear等。

可以從Maven的命令列輸出中看到在專案構建過程執行了哪些外掛目標。

自定義繫結

除了內建繫結以外,使用者還能夠自己選擇將某個外掛目標繫結到生命週期的某個階段上。這種自定義繫結方式能讓Maven專案在構建過程中執行更多更富特色的任務。

一個常見的例子是建立專案的原始碼jar包,內建的外掛繫結關係中並沒有涉及這一任務,因此需要使用者自行配置。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>2.1.1</version>
            <executions>
                <execution>
                    <id>attach-sources</id>
                    <phase>verify</phase>
                    <goals>
                        <goal>jar-no-fork</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

在POM的build元素下的plugins子元素中宣告外掛的使用,該例中用到的是maven-source-plugin,其groupId為org.apache.maven.plugins,這也是Maven官方外掛的groupId,緊接著artifactId為maven-source-plugin,version為2.1.1。對於自定義繫結的外掛,使用者總是應該宣告一個非快照版本,這樣可以避免由於外掛版變化造成的構建不穩定性。

上述配置中,除了基本的外掛座標宣告外,還有外掛執行配置,executions下每個execution子元素可以用來配置執行一個任務。該例中配置了一個id為attach-sources的任務,通過phrase配置,將其繫結到verify生命週期階段上,再通過goals配置指定要執行的外掛目標。至此,自定義外掛繫結完成。

有時候,即使不通過phase元素配置生命週期階段,外掛目標也能夠繫結到生命週期中去。例如,可以嘗試刪除上述配置中的phase一行,再次執行mvn verify,仍然可以看到maven-source-plugin:jar-no-fork得以執行。出現這種現象的原因是:有很多外掛的目標在編寫時已經定義了預設繫結階段。可以使用maven-help-plugin檢視外掛詳細資訊,瞭解外掛的預設繫結階段。執行命令如下:

$ mvn help:describe-Dpulgin=org.apache.maven.plugins:maven-source-plugin:2.1.1-Ddetail

該命令輸出對應的詳細資訊。

我們知道,當外掛目標被繫結到不同的生命週期階段的時候,其執行順序會由生命週期階段的現後順序決定。如果多個目標被繫結到同一個階段,他們的執行順序會是怎樣?答案很簡單,當多個外掛目標繫結到同一個階段的時候,這些外掛宣告的先後順序決定了目標的執行順序。