好久沒有更新了,在這里給大家說聲抱歉,實在是因為最近加班忙成狗,還有一個原因是我想把《maven
實戰》這本書剩下的最后幾個章節看完在統一做筆記,所以......,好了閑話少許,現在開始我們今天的聚合與繼承章節的知識要點回顧
maven
的聚合特性能夠把項目的各個模塊都聚合在一起構建,而maven
的繼承特性則能夠幫助抽取各個模塊相同的依賴和插件等配置,從而讓項目像OPPO
那樣從這一刻更清晰
聚合
聚合的目的是為了實現多個模塊同時構建,為了配置聚合,我們需要創建獨立的模塊,為模塊編寫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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zheng</groupId>
<artifactId>account-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>parent project name</name>
<modules>
<module>module1-artifactId</module>
<module>module2-artifactId</module>
</modules>
</project>
該項目只需要提供上面的pom.xml
配置文件即可,其他src
也不需要,這里的packaging
必須為pom
,否則無法構建
為了方便構建,通常將聚合模塊作為項目目錄的最頂層,其他被聚合的子模塊作為項目目錄的子目錄存在
maven
在編譯時會根據pom.xml
中配置的modules
得出一個反應堆構建順序,并按照這個順序編譯項目模塊
建議我們在創建項目的時候為項目模塊提供一個合理的name
,因為構建的結果中是通過各個模塊中配置的name
來標識每一個項目模塊的構件狀態的
如下所示,是對一個account-parent
項目的構件結果:
繼承
繼承目的是為了將一些公共的配置抽取出來,方便其他模塊共用,為了實現模塊繼承,需要以下幾步:
- 創建一個新的項目模塊,并配置其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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zheng</groupId>
<artifactId>account-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>parent project name</name>
</project>
跟聚合一樣,父模塊中的packaging也必須要求是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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.zheng</groupId>
<artifactId>account-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../account-parent/pom.xml</relativePath>
</parent>
<groupId>com.zheng</groupId>
<artifactId>account-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>parent project name</name>
</project>
上面通過parent
加入父模塊在maven
倉庫中的坐標來引用maven
通過relativePath
相對路徑的方式指定了父模塊基于當前子模塊的位置,maven
在構建子模塊的時候就不會要求父模塊一定要先于安裝到本地倉庫,因為通過該標簽指定的相對路徑已經可以明確指定到父模塊,當然如果本地倉庫和relativePath
所提供的路徑找不到父模塊,那么構建將會失敗
可繼承的pom元素
groupId
: 項目組id,項目坐標核心元素
version
: 項目版本,項目坐標核心元素
description
: 項目描述信息
organization
: 項目組織信息
inceptionYear
: 創始年份
url
: 項目地址,這里可以向項目的index連接
developers
: 項目開發者信息
contributors
: 項目貢獻者信息
distributionManagement
: 項目的部署地址
issueManagement
: 項目缺陷跟蹤信息
ciManagement
: 項目持續集成的部署信息
scm
: 項目的版本控制系統信息
mailingLists
: 項目的郵件地址列表信息
properties
: 自定義的maven屬性
dependencies
: 項目依賴
dependencyMangement
: 項目依賴管理配置
repositories
: 項目倉庫
build
: 項目源碼目錄配置、輸出目錄配置、插件配置、插件管理配置等
reporting
: 項目的輸出目錄配置、報告插件配置等
通過build參數可以看到插件配置也可以被繼承
依賴管理
dependencies
與dependencyManagement
在父模塊pom.xml
中的dependencies
中引入的依賴會被所有引用該父模塊的子模塊繼承,但并不是所有的子模塊都會用到父模塊中聲明的依賴,所以為了防止多余的依賴,父容器中可以通過dependencyManagement
來聲明jar
包依賴。
dependencyManagement
中聲明的依賴配置會被子模塊繼承,但是不會被實際使用,除非子模塊顯示通過groupId:artifactId
聲明需要引用該依賴
使用dependencyManagement
的好處是可以在父模塊中對jar
包版本進行統一管理,推薦這么做
import依賴范圍
在前面依賴范圍提到過import
,它的作用只會對pom.xml
中配置的dependencyManagement
有效
import
的作用是:將目標pom
中的dependencyManagement
配置導入并合并到當前pom.xml
中
import
依賴范圍是除了使用代碼復制和繼承之外的又一個可以將外部配置導入的方式,下面是具體配置:
父項目b
<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.cbm.stu</groupId>
<artifactId>maven-parent-b</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<name>maven-parent-b</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.40</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
繼承b
的子項目
<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.cbm.stu</groupId>
<artifactId>maven-study-mail</artifactId>
<version>2.1</version>
<packaging>jar</packaging>
<name>maven-study-mail</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencyManagement>
<dependencies>
<!-- 此處繼承b 項目,type為pom,scope 為 import -->
<dependency>
<groupId>com.cbm.stu</groupId>
<artifactId>maven-parent-b</artifactId>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- 從繼承的父項目中繼承依賴 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
import
依賴范圍由于其特殊性,它的類型(type
)一般都是pom
,scope
為import
插件管理
與依賴管理相似的是插件管理,maven中提供了plugins
, pluginManagement
兩個元素,這兩個元素的用途與依賴管理中的dependencies
和dependencyManagement
用法一致
這里不做贅述
聚合與繼承之間的關系
不同點:
- 聚合與繼承是兩個概念,其目的是完全不同的,聚合是為了解決多模塊同時構建的問題,而繼承則是為了解決多模塊重復配置問題
- 對于聚合模塊來說,它知道有哪些子模塊需要被聚合,(<
modules
>),而對于繼承來說它不知道有哪些子模塊繼承了它,但相反,子模塊知道他們繼承的是哪一個父模塊(<parent
>)
聚合模塊.png
繼承模塊.png
相同點:
聚合與繼承模塊pom
的類型(type
)都是pom
,他們都除了包含一個pom.xml
文件之外,沒有其他東西
推薦做法:為了方便,可以將聚合和繼承兩者合成一個模塊,在一個父模塊中配置聚合和繼承
約定優于配置
使用maven
比使用ant
配置更少,更方便,雖然用戶感覺上自己配置的東西少了,其實是maven
內部將某一些配置提前預設好了,比如在超級pom
中可以看到的:
- 源碼目錄為
src/main/java
- 編譯輸出目錄為
target/classes
- 打包方式為
jar
- 包輸出目錄為
target/
所有項目的pom.xml
都繼承與超級pom
中的配置,超級pom
具體位置在:
${MVN_HOME}/lib/maven-model-builder-x.x.x.jar/org/apache/maven/model/pom-4.0.0.xml
反應堆
對于單模塊,反應堆就是它本身,但對于多個模塊項目來說,反應堆就包含了模塊之間繼承與依賴的關系
maven
的實際構建順序是這樣形成的:
-
maven
按序讀取pom,如果該pom
沒有依賴模塊,則直接進行構建 - 如果依賴了其他模塊,那么先構建其他模塊
- 遞歸1,2直到完成整個項目的構建工作
特別說明,項目模塊之間的依賴配置,不能出現循環依賴的現象,也就是A依賴B,B也依賴于A,這樣的配置將會導致maven構建失敗
裁剪反應堆
對聚合模塊運行maven
命令比如mvn clean install
,maven
會根據計算出來的反應堆順序將全部子模塊都構建完畢并安裝到本地倉庫,為了選擇性的構件某些模塊進行構建而不是將所有模塊進行構建,那么可以采用maven
提供的幾條裁剪反應堆命令:
-am also make
構建模塊同時構建所列模塊依賴的其他模塊
-amd also make dependency
構建模塊同時構建依賴當前模塊的其他模塊
-pl --projects
構建指定的模塊,多個模塊用,分隔
-rf resume-from
在計算出的反應堆順序基礎上,從指定模塊開始向后構建
下面是各個命令的實例:
假設存在account-parent
,account-email
,account-persist
三個模塊,他們之間的關系如下:
-pl
:構建指定模塊mvn clean install -pl account-parent
將會構建
account-parent
模塊
-am
:構建模塊并構建其依賴的其他模塊
mvn clean install -pl account-email -am
將會構建account-parent/account-email模塊
-amd
: 構建模塊并構建依賴它的其他模塊
mvn clean install -pl account-parent -amd
將會構建account-parent/account-email/account-persist
-rf
指定構建的起始模塊,假設模塊依賴關系如下
account-parent
- account-email
- account-persist
mvn clean install -pl account-parent -amd -rf account-persist
將會構建account-parent/account-persist
,而跳過account-email
模塊的構建
好了,以上就是本章的重點知識,鍵盤敲到這里,再看看現在的時間0:39,再想到明天臺風天還要上班,趕緊洗干凈滾床上睡覺啦!!!