Maven:聚合。
我們會想要一次構建兩個專案,而不是到兩個模組的目錄下分別執行mvn命令。Maven聚合(或者稱為多模組)這一特性就是為該需求服務的。
為了能夠使用一條命令就能構建a和b兩個模組,我們需要建立一個額外的名為c的模組,然後通過該模組構建整個專案的所有模組。c本身作為一個Maven專案,他必須要有自己的POM,不過,同時作為一個聚合專案,其POM又有特殊的地方。如下c的pom.xml內容。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.test</groupId> <artifactId>c</artifactId> <version>1.0.0-SNAPSHOT</version> <packaging>pom</packaging> <name>c</name> <modules> <module>a</module> <module>b</module> </modules> </project>
上述POM依舊使用了賬戶註冊服務共同的groupId com.test,artifactId為獨立的c,版本也與其他兩個模組一致,為1.0.0-SNAPSHOT.這裡的第一個特殊的地方為packaging,即使用了預設值jar。對於聚合模組來說,其打包方式packaging的值必須為pom,否則就無法構建。
POM的name欄位是為了給專案提供一個更容易閱讀的名字。元素modules,這是實現聚合的最核心的配置。使用者可以通過在一個打包方式為pom的Maven專案中宣告任意數量的module元素來實現模組的聚合。這裡每個module的值都是一個當前POM的相對目錄,譬如該例中,c的POM的路徑為D:\...\workspace\c\pom.xml,那麼a就對應了目錄D:\...\workspace\a\,而b對應於目錄D:\...\workspace\b\。這兩個目錄各自包含了pom.xml、src/main/java/、src/test/java/等內容,離開c也能獨自構建。
一般來說,為了方便快速定位內容,模組所處的目錄名稱應當與其artifactId一致,不過這不是Maven的要求,使用者也可以將a專案放到d/目錄下。這時,聚合的配置就需要相應的改成<module>d</module>。
為了方便使用者構建專案,通常將聚合模組放在專案目錄的最頂層,其他模組則作為聚合模組的子目錄存在,這樣當用戶得到原始碼的時候,第一眼發現的就是聚合模組的POM,不用從多個模組中去尋找聚合模組來構建整個專案。
c的內容僅是一個pom.xml檔案,他不像其他模組那樣有src/main/java、src/test/java等目錄。這也是容易理解的,聚合模組僅僅是幫助聚合其他模組構建的工具,他本身並無實質的內容。
關於目錄結構還需要注意的是,聚合模組與其他模組的目錄結構並非一定要是父子關係,例如平行的目錄結構。
如果使用平行目錄結構,聚合模組的POM也需要做相應的修改,以指向正確的模組目錄:
<modules>
<module>../a</module>
<module>../b</module>
</modules>
從聚合模組執行mvn clean install命令時,Maven會首先解析聚合模組的POM、分析要構建的模組、並計算出一個反應堆構建順序,然後根據這個順序依次構建各個模組。反應堆是所有模組組成的一個構建結構。
控制檯輸出中顯示的各模組的名稱,而不是artifactId,這也解釋了為什麼要在POM中配置合理的name欄位,其目的是讓Maven的構建輸出更清晰。輸出的最後是一個專案構建的小結報告,包括各個模組構建成功與否、花費的時間,以及整個構建花費的時間、使用的記憶體等。