讀古今文學網 > Maven實戰 > 8.2 聚合 >

8.2 聚合

到目前為止,本書實現了用戶註冊服務的兩個模塊,它們分別是第5章實現的account-email和本章實現的account-persist。這時,一個簡單的需求就會自然而然地顯現出來:我們會想要一次構建兩個項目,而不是到兩個模塊的目錄下分別執行mvn命令。Maven聚合(或者稱為多模塊)這一特性就是為該需求服務的。

為了能夠使用一條命令就能構建account-email和account-persist兩個模塊,我們需要創建一個額外的名為account-aggregator的模塊,然後通過該模塊構建整個項目的所有模塊。account-aggregator本身作為一個Maven項目,它必須要有自己的POM,不過,同時作為一個聚合項目,其POM又有特殊的地方。如下為account-aggregator的pom.xml內容,見代碼清單8-9。

代碼清單8-9 account-aggregator的POM

上述POM依舊使用了賬戶註冊服務共同的groupId com.juvenxu.mvnbook.account,artifactId為獨立的account-aggregator,版本也與其他兩個模塊一致,為1.0.0-SNAPSHOT。這裡的第一個特殊的地方為packaging,其值為POM。回顧account-email和account-persist,它們都沒有聲明packaging,即使用了默認值jar。對於聚合模塊來說,其打包方式packaging的值必須為pom,否則就無法構建。

POM的name字段是為了給項目提供一個更容易閱讀的名字。之後是本書之前都沒提到過的元素modules,這是實現聚合的最核心的配置。用戶可以通過在一個打包方式為pom的Maven項目中聲明任意數量的module元素來實現模塊的聚合。這裡每個module的值都是一個當前POM的相對目錄,譬如該例中,account-aggregator的POM的路徑為D:\…\code\ch-8\account-aggregator\pom.xml,那麼account-email就對應了目錄D:\…\code\ch-8\account-aggregator\account-email/,而account-persist對應於目錄D:\…\code\ch-8\account-aggregator\account-persist/。這兩個目錄各自包含了pom.xml、src/main/java/、src/test/java/等內容,離開account-aggregator也能獨立構建。

一般來說,為了方便快速定位內容,模塊所處的目錄名稱應當與其artifactId一致,不過這不是Maven的要求,用戶也可以將account-email項目放到email-account/目錄下。這時,聚合的配置就需要相應地改成<module>email-account</module>。

為了方便用戶構建項目,通常將聚合模塊放在項目目錄的最頂層,其他模塊則作為聚合模塊的子目錄存在,這樣當用戶得到源碼的時候,第一眼發現的就是聚合模塊的POM,不用從多個模塊中去尋找聚合模塊來構建整個項目。圖8-1所示為account-aggregator與另外兩個模塊的目錄結構關係。

從圖8-1中能夠看到,account-aggregator的內容僅是一個pom.xml文件,它不像其他模塊那樣有src/main/java、src/test/java等目錄。這也是容易理解的,聚合模塊僅僅是幫助聚合其他模塊構建的工具,它本身並無實質的內容。

關於目錄結構還需要注意的是,聚合模塊與其他模塊的目錄結構並非一定要是父子關係。圖8-2展示了另一種平行的目錄結構。

圖8-1 聚合模塊的父子目錄結構

圖8-2 聚合模塊的平行目錄結構

如果使用平行目錄結構,聚合模塊的POM也需要做相應的修改,以指向正確的模塊目錄:

最後,為了得到直觀的感受,看一下從聚合模塊運行mvn clean install命令會得到怎樣的輸出:

會首先解析聚合模塊的POM、分析要構建的模塊、並計算出一個反應堆構建順序(Reactor Build Order),然後根據這個順序依次構建各個模塊。反應堆是所有模塊組成的一個構建結構。8.6節會詳細講述Maven的反應堆。

上述輸出中顯示的是各模塊的名稱,而不是artifactId,這也解釋了為什麼要在POM中配置合理的name字段,其目的是讓Maven的構建輸出更清晰。輸出的最後是一個項目構建的小結報告,包括各個模塊構建成功與否、花費的時間,以及整個構建花費的時間、使用的內存等。