在實際項目的使用中,經常會對項目進行模塊劃分,以下降耦合。如服務接口模塊,各業務模塊,web模塊等。而模塊間共享一些相同的依賴,彼此間也緊密聯繫。此時咱們就能夠經過maven的聚合和繼承來管理模塊。java
好比如今咱們有如下模塊:web
模塊間的關係是example-web和example-service經過example-api相鏈接。spring
example-web -> example-api <- example-service
此時咱們能夠建立一個聚合模塊example-parent,也能夠稱做父模塊。它的pom.xml以下apache
<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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.lcifn.maven</groupId> <artifactId>example-parent</artifactId> <version>0.0.1</version> <packaging>pom</packaging> <name>example</name> <modules> <module>example-api</module> <module>example-service</module> <module>example-web</module> </modules> </project>
對於聚合模塊來講,其打包方式packaging的值必須爲pom,不然沒法構建。通常聚合模塊的內容僅是一個pom.xml,它就是幫助聚合其餘模塊構建的工具。api
而對於子模塊來講,經過繼承父pom,將公共的配置統一在父pom中管理,好比依賴的版本以及插件的管理。maven
以example-api爲例工具
<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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.lcifn.maven</groupId> <artifactId>example-parent</artifactId> <version>0.0.1</version> </parent> <artifactId>example-api</artifactId> <version>0.0.1</version> </project>
parent標籤內的子元素groupId,artifactId和version指定父模塊的座標。對於子模塊,父模塊的pom中不少元素是能夠繼承的ui
以上只是列舉了經常使用的一些元素插件
實際使用時,聚合模塊和父模塊每每是同一模塊。code
項目中依賴的spring多個組件但願都是同一版本的,這樣能避免因版本問題出現的奇怪錯誤,能夠經過maven的dependencyManagement來管理。在dependencyManagement元素下的依賴聲明不會引入實際的依賴,而它能夠約束dependencies下的依賴的使用。
在父模塊的pom中加入配置
<properties> <spring.version>4.1.6.RELEASE</spring.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> </dependencies> </dependencyManagement>
將經常使用的依賴版本以maven變量提取出來,消除重複,並方便之後升級。
在子模塊的pom文件中,只須要配置groupId和artifactId就能得到對應的依賴信息,從而可讓多個模塊統一使用統一版本的依賴,減小依賴衝突。
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> </dependency> </dependencies>
maven也提供了pluginManagement元素幫助管理插件,在該元素中配置的依賴不會形成實際的插件調用行爲,當子模塊的pom中配置了真正的plugin元素,而且groupId和artifactId與pluginManagement中配置的插件匹配時,pluginManagement的配置纔會產生真正的影響。
父模塊的pom文件,配置maven-source-plugin,將jar-no-fork目標綁定到verify生命週期階段,生成項目源碼包。
<pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> <version>3.0.1</version> <executions> <execution> <id>attach-sources</id> <phase>verify</phase> <goals> <goal>jar-no-fork</goal> </goals> </execution> </executions> </plugin> </plugins> </pluginManagement>
當子模塊須要生成源碼包時,只須要簡單配置
<plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> </plugin> </plugins>
maven提倡「約定優於配置」,從而能夠減小大量的配置。一個項目構建要完成的最基本的事情,包括清除構建目錄,建立目錄,編譯代碼,複製依賴至目標目錄,最後打包。若是使用ant,須要在配置文件中指定源碼目錄是什麼,編譯目標目錄是什麼,分發目錄是什麼等等。而使用maven後,用戶付出必定的代價來遵照manven的約定,便可用很是簡單的pom文件來達到相同的目的。
maven對用戶目錄的約定以下
這些默認的約定定義在maven的超級pom文件中,任何一個Maven項目都隱式繼承該pom,有點相似jave類都繼承於Object類。對於maven3,超級pom文件在$MAVEN_HOME$/lib/maven-model-builder-3.3.1.jar
中的org\apache\maven\model\pom-4.0.0.xml。
簡單列舉下超級pom中對項目結構的定義
<build> <directory>${project.basedir}/target</directory> <outputDirectory>${project.build.directory}/classes</outputDirectory> <finalName>${project.artifactId}-${project.version}</finalName> <testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory> <sourceDirectory>${project.basedir}/src/main/java</sourceDirectory> <scriptSourceDirectory>${project.basedir}/src/main/scripts</scriptSourceDirectory> <testSourceDirectory>${project.basedir}/src/test/java</testSourceDirectory> <resources> <resource> <directory>${project.basedir}/src/main/resources</directory> </resource> </resources> <testResources> <testResource> <directory>${project.basedir}/src/test/resources</directory> </testResource> </testResources> </build>
在一個多模塊的Maven項目中,反應堆(Reactor)指全部模塊組成的一個構建結構。對於單模塊的項目,反應堆就是模塊自身,而對於多模塊項目,反應堆就包含了各模塊之間繼承與依賴的關係,從而可以自動計算合理的模塊構建順序。
上述example-parent的構建順序就是
模塊間的依賴關係會將反應堆構成一個有向非循環圖。當出現兩個模塊相互依賴時,maven會報錯。
有些時候,用戶會想僅僅構建完整反應堆的某些個模塊,即裁剪反應堆。maven提供命令支持裁剪反應堆。
可使用-pl指定構建某幾個模塊
mvn clean install -pl example-api,example-service
使用-am同時構建所列模塊的依賴模塊
mvn clean install -pl example-service -am
使用-amd構建依賴於所列模塊的模塊
mvn clean install -pl example-api -amd
使用-rf在完整反應堆構建順序基礎上指定從哪一個模塊開始構建
mvn clean install -rf example-service
在開發過程當中,靈活應用上述參數,能夠幫助咱們跳過無須構建的模塊,從而加速構建,尤爲在項目龐大,模塊衆多的時候。