標簽(空格分隔): 學習筆記
Maven的聚合特性能夠把項目的各個模塊聚合在一起構建;
Maven的繼承特性能夠幫助抽取各模塊相同的依賴和插件等配置,在簡化POM的同時,還能夠促進各個模塊配置的一致性。
account-persist模塊
POM文件
<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.park.mvnDemo.account</groupId>
<artifactId>account-persist</artifact>
<name>Account Persist</name>
<version>1.0.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifact>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifact>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifact>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifact>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifact>
<version>4.7</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<testResources>
<testResource>
<directory>src/test/resources</directory>
<filtering>true</filtering>
</testResource>
</testResources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
account-persist模塊還需要一個SpringFramework的配置文件,位於src/main/resources
目錄:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="propertyConfigure" class="org.springframework.beans.factory.config.PropertyPlaceholderconfigure">
<property name="location" value="classpath:account-service.properties"/>
</bean>
<bean id="accountPersistService" class="com.park.mvnDemo.account.persist.AccountPersistServiceImpl">
<property name="file" value="${persist.file}"/>
</bean>
<beans>
聚合
我們想要一次構建兩個項目,而不是到兩個模塊的目錄下分別執行mvn
命令 -- Maven的聚合就是為該需求服務的。
為了能夠使用一條命令就能構建account-email
和account-persist
兩個模塊,需要創建一個額外的名為account-aggregator
的模塊,然后通過該模塊構建整個項目的所有模塊。
account-aggregator
也有它自己的POM文件,內容如下:
<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.park.mvnDemo.account</groupId>
<artifactId>account-aggregator</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Account Aggregator</name>
<modules>
<module>account-email</module>
<module>account-persist<module>
</modules>
</project>
在上面的xml文件中,
packaging
的方式為pom。對於聚合模塊來說,其打包方式必須為pom,否則無法構建!
- modules: 這里是實現聚合的最核心的配置,可以聲明任意數量的module元素來實現元素的聚合;
- 其中,每個module的值為當前POM的相對路徑;
- 如:當前POM位於
D:\m2\code\account-aggregator\pom.xml
, 另有一個項目A位於D:\m2\code\account-aggregator\account-email/
,一個項目B位於D:\m2\code\-aggregatoraccount\account-persist/
,與上面的module值相對應。 - 為了方便用戶構建項目,通常將聚合模塊放在項目目錄的最頂層,其他模塊則作為聚合模塊的子目錄存在。
繼承
在我們已經聚合的項目中,有很多重復的配置,有相同的groupId和version,有相同的spring-core, spring-beans, spring-context和juit依賴,造成大量的浪費也會引發問題,所以如何使用繼承機制來統一配置這些重復的信息,做到”一處聲明,處處使用“呢?
思路:創建POM的父子結構,在父POM中聲明一些配置供子POM繼承、
父模塊
在account-aggregator
目錄下創建POM的父目錄account-parent
,內部的pom文件內容為:
<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.park.mvnDemo.account</groupId>
<artifactId>account-parent</artifactId>
<version>1.0.0</version>
<packaging>dom<packaging>
<name>Account Parent</name>
</project>
作為父模塊的POM,其打包類型也是只能為pom。
由於父模塊只是為了幫助消除配置的重復,因此她本身不包含除POM外的項目文件,也就不需要src/main/java
之類的文件了。
子模塊 -- account-email
<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>
<parent>
<groupId>com.park.mvnDemo.account</groupId>
<artifactId>account-parent</artifactId>
<version>1.0.0</version>
<relativePath>../account-parent/pom.xml</relativePath>
</parent>
<artifactId>account-email</artifactId>
<name>Account Email</name>
<dependencies>
...
</dependencies>
<build>
<plugins>
...
</plugins>
</build>
</project>
(子模塊account-persist的pom配置與之類似,不再贅述)
聚合模塊 -- account-aggregator
<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.park.mvnDemo.account</groupId>
<artifactId>account-aggregator</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>dom</packaging>
<name>Account Aggregator</name>
<modules>
<module>account-parent</module>
<module>account-email</module>
<module>account-persist</module>
</modules>
</project>
可繼承的POM元素
- groupId: 項目組ID,項目坐標的核心坐標;
- version: 項目版本,項目坐標的核心坐標;
- description: 項目的描述信息;
- organization: 項目的組織信息;
- inceptionYear: 項目的創始年份;
- url: 項目的URL地址;
- developers: 項目的開發者信息;
- contributors: 項目的貢獻值和信息;
- distributionManagement: 項目的部署配置;
- issueManagement: 項目的缺陷跟蹤系統;
- ciManagement: 項目的持續集成系統信息;
- scm: 項目的版本控制系統信息;
- mailingLists: 項目的郵件列表信息;
- properties: 自定義的Maven屬性;
- dependencies: 項目的依賴配置;
- dependencyManagement: 項目的依賴管理配置;
- repositories: 項目的倉庫配置;
- build: 包括項目的源碼目錄配置、輸出目錄配置、插件配置、插件管理配置等;
- reporting: 包括項目的報告輸出目錄配置、報告插件配置等。
依賴管理
dependencies可以使得子模塊繼承父模塊依賴的插件,同時dependencyManagement元素又能保證子模塊使用的靈活性。在dependencyManagement元素下的聲明不會引入實際的依賴,不過它能夠約束dependencies下的依賴使用。
示例:
(一) 在account-parent中配置dependencyManagement元素
<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.park.mvnDemo.account</groupId>
<artifactId>account-parent</artifactId>
<version>1.0.0_SNAPSHOT</version>
<packaging>dom</packaging>
<name>Account Parent</name>
<properties>
<springframework.version>2.5.6</springframework.version>
<junit.version>4.7</junit.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifact>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</depedencyManagement>
</project>
(二) 繼承了dependencyManagement的account-email POM
<properties>
<javax.mail.version>1.4.1</javax.mail.version>
<greenmail.version>1.3.1b</greenmail.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>${javax.mail.version}</version>
</dependency>
<dependency>
<groupId>com.icegreen</groupId>
<artifactId>greenmail</artifactId>
<version>${greenmail.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
如果不聲明某個依賴,那這個依賴就不會被引入。
插件管理
Maven提供了pluginManagement元素來管理插件。在該元素中配置的依賴不會造成實際的插件調用行為,當POM中配置了真正的plugin元素,並且其groupId和artifactId與pluginManagement中配置的插件相匹配時,pluginManagement的配置才會影響實際的插件行為。
(一) 在父POM中配置pluginManagement
<build>
<pluginManagement>
<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>
</exeuction>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
(二) 在子模塊中配置相應的插件
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
</plugin>
</plugins>
</build>
聚合與繼承的關系
- 聚合是為了方便快速構件項目。對於聚合模塊來說,它知道有哪些被聚合的模塊,但那些模塊不知道這個聚合模塊的存在;
- 繼承是為了消除重復配置。對於繼承關系的父POM來說,它不知道有哪些子模塊繼承於它,但是子模塊必須知道自己的父POM是什么。
在實際的項目中,一個POM可以既是聚合POM,又是父POM。
如果父模塊位於子模塊們的上級,則不需要再額外配置relativePath
,因為Maven默認能識別父模塊的位置。
反應堆(Reactor)
在一個多模塊的Maven項目中,反應堆是指所有模塊組成的一個構件結構。包含了各模塊之間繼承於依賴的關系,從而能夠自動計算出合理的模塊構件順序。
Maven實際的構建順序是:Maven按序讀取POM,如果該POM沒有依賴模塊,那么就構建該模塊,否則就先構建其依賴模塊,如果該依賴模塊還依賴於其他模塊,則進一步先構建其他模塊。
模塊間的依賴關系會將反應堆構成一個有向無環圖(DAG: Directed Acyclic Graph),各個模塊是該圖的節點,依賴關系構成了有向邊。
裁剪反應堆
當用戶並不想構建整個項目的時候,就需要實時地裁剪反應堆。
Maven提供很多命令行支持裁剪反應堆:
-
-am, --alsomake
: 同時構建所列模塊的依賴模塊模塊; -
-amd, --also-make-dependents
: 同時構建依賴於所列模塊的模塊; -
-pl, --projects<arg>
: 構建指定模塊,模塊間用逗號分割; -
-rf, -resume-from<arg>
: 從指定的模塊回復反應堆。$ mvn clean install
\\Output: Account Aggregator, Account Parent, Account Email, Account Persist
$ mvn clean install -pl account-email,account-persist
\\Output: Account Email, Account Persist
$ mvn clean install -pl account-email -am
\\Output: Account Parent, Account Email
$ mvn clean install -pl account-parent -amd
\\Output: Account Parent, Account Email, Account Persist
$ mvn clean install -rf account-email
\\Output: Account Email, Account Persist
$ mvn clean install -pl account-parent -amd -rf account-email
\\Output: Account Email, Account Persist