1. 程式人生 > >Maven POM 檔案中的中的繼承(Inheritance)和 聚合(Aggregation)- IDEA 和 Eclipse 中多模組專案的 Maven 組織方法

Maven POM 檔案中的中的繼承(Inheritance)和 聚合(Aggregation)- IDEA 和 Eclipse 中多模組專案的 Maven 組織方法

Maven POM 檔案中的繼承和聚合(Inheritance & Aggregation)

之前在 IDEA 裡建了一個專案專門用來學習,每個知識點都建立一個相應的模組,方便學習和檢視。今天在建第二個模組的時候發現,這個模組很多的 Maven 依賴和第一個模組相同,按照我之前一個專案僅一個模組的做法,那肯定是要把依賴再複製貼上一遍。但是在同一個專案裡面,隨著模組不斷增加,不能每次都複製貼上吧,而且模組都是 Maven 工程,可以利用 Maven 來對這些模組進行管理。帶著這種想法,我去官網學習了下 POM 檔案中的繼承和聚合。

POM

POM (Project Object Model),在我們的 Maven 專案中表現出來的就是 pom.xml 檔案,是對整個 Maven 專案的組織管理檔案。

Super POM

我們建立 Maven 專案的時候,或是手動建立或是自動建立,都會有一個固定的檔案目錄結構,那為什麼必須是按照這個結構來呢?新增依賴後,專案自動會從 Maven 中央倉庫下載相關的 jar 包,它是在什麼地方定義這個倉庫地址的?這些問題的答案就是 Super POM。我們在專案中建立的 POM 檔案都是繼承自這個 Super POM,它是 Maven 專案的預設 POM。下面是 Maven 2.1.x 版本的 Super POM,能看到其中定義了很多預設的配置。

<project>
  <modelVersion>4.0.0</modelVersion
>
<name>Maven Default Project</name> <repositories> <repository> <id>central</id> <name>Maven Repository Switchboard</name> <layout>default</layout> <url>http://repo1.maven.org/maven2</url> <snapshots
>
<enabled>false</enabled> </snapshots> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>central</id> <name>Maven Plugin Repository</name> <url>http://repo1.maven.org/maven2</url> <layout>default</layout> <snapshots> <enabled>false</enabled> </snapshots> <releases> <updatePolicy>never</updatePolicy> </releases> </pluginRepository> </pluginRepositories> <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> <!-- TODO: MNG-3731 maven-plugin-tools-api < 2.4.4 expect this to be relative... --> <scriptSourceDirectory>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> <pluginManagement> <plugins> <plugin> <artifactId>maven-antrun-plugin</artifactId> <version>1.3</version> </plugin> <plugin> <artifactId>maven-assembly-plugin</artifactId> <version>2.2-beta-2</version> </plugin> <plugin> <artifactId>maven-clean-plugin</artifactId> <version>2.2</version> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>2.0.2</version> </plugin> <plugin> <artifactId>maven-dependency-plugin</artifactId> <version>2.0</version> </plugin> <plugin> <artifactId>maven-deploy-plugin</artifactId> <version>2.4</version> </plugin> <plugin> <artifactId>maven-ear-plugin</artifactId> <version>2.3.1</version> </plugin> <plugin> <artifactId>maven-ejb-plugin</artifactId> <version>2.1</version> </plugin> <plugin> <artifactId>maven-install-plugin</artifactId> <version>2.2</version> </plugin> <plugin> <artifactId>maven-jar-plugin</artifactId> <version>2.2</version> </plugin> <plugin> <artifactId>maven-javadoc-plugin</artifactId> <version>2.5</version> </plugin> <plugin> <artifactId>maven-plugin-plugin</artifactId> <version>2.4.3</version> </plugin> <plugin> <artifactId>maven-rar-plugin</artifactId> <version>2.2</version> </plugin> <plugin> <artifactId>maven-release-plugin</artifactId> <version>2.0-beta-8</version> </plugin> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>2.3</version> </plugin> <plugin> <artifactId>maven-site-plugin</artifactId> <version>2.0-beta-7</version> </plugin> <plugin> <artifactId>maven-source-plugin</artifactId> <version>2.0.4</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.4.3</version> </plugin> <plugin> <artifactId>maven-war-plugin</artifactId> <version>2.1-alpha-2</version> </plugin> </plugins> </pluginManagement> </build> <reporting> <outputDirectory>${project.build.directory}/site</outputDirectory> </reporting> <profiles> <profile> <id>release-profile</id> <activation> <property> <name>performRelease</name> <value>true</value> </property> </activation> <build> <plugins> <plugin> <inherited>true</inherited> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> <executions> <execution> <id>attach-sources</id> <goals> <goal>jar</goal> </goals> </execution> </executions> </plugin> <plugin> <inherited>true</inherited> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-javadoc-plugin</artifactId> <executions> <execution> <id>attach-javadocs</id> <goals> <goal>jar</goal> </goals> </execution> </executions> </plugin> <plugin> <inherited>true</inherited> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-deploy-plugin</artifactId> <configuration> <updateReleaseInfo>true</updateReleaseInfo> </configuration> </plugin> </plugins> </build> </profile> </profiles> </project>

Minimal POM

既然 Super POM 中已經有很多預設的 Maven 配置,那麼對於我們自己建立的 POM 檔案,如果不需要新增額外的功能,只需要定義最小配置即可。參考如下

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1</version>
</project>

即專案的基本資訊,其中<modelVersion>應該被設為4.0.0<groupId><artifactId><version>提供了專案組織id、專案id以及專案版本號。

專案繼承

Super POM 就是一個典型的 POM 繼承的例子。我們也可以自己定義模組之間的繼承方式,從父模組的 POM 配置中繼承配置資訊,子模組就不再需要進行重複的配置。

這裡有兩個模組(或者稱為構件:artifact),my-app 和 my-module 模組。其中 my-module 模組繼承自 my-app 模組,即 my-app 模組是 my-module 模組的父模組。根據兩個模組之間不同的組織結構,有兩種不同的配置方法。

對於 IDEA 來說,可以建立一個 Maven 工程,再在其中新增 Maven 模組,配置模組繼承工程的 POM ,這樣的話專案目錄結構就是 Example 1。也可以建立一個空的工程,在其中新增多個 Maven 模組,配置模組之間的 POM 關係實現繼承,這樣專案目錄結構就是 Example 2。對於 Eclipse 來說,就只能建立 Example 2 的目錄結構了。

  • 第一種結構 Example 1:
my-app
 |-- my-module
 |   `-- pom.xml
 `-- pom.xml

my-module 模組是 my-app 模組的一部分,處於 my-app 模組的根目錄下,與 my-app 的 pom.xml 檔案平級。這裡可以通過在子模組 my-module 裡的 POM 中新增一下內容實現繼承。

<project>
  <parent>
    <groupId>com.mycompany.app</groupId>
    <artifactId>my-app</artifactId>
    <version>1</version>
  </parent>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-module</artifactId>
  <version>1</version>
</project>

這裡在<project>中指定了<parent>元素,其中聲明瞭父模組的組織資訊。如果希望子模組繼承父模組的<groupId><version>,刪掉子模組中的<groupId><version>即可。

  • 第二種結構 Example 2:
.
 |-- my-module
 |   `-- pom.xml
 `-- my-app
     `-- pom.xml

這種結構中,my-module 和 my-app 模組在相同的目錄下,兩者之間處於平級關係。Eclipse 中各個專案之間就是這種目錄層級關係。這種情況下我們可以新增一個<relativePath>元素到子模組的<parent>中,來實現繼承關係,而其值就是 POM 檔案的相對路徑。

<project>
  <parent>
    <groupId>com.mycompany.app</groupId>
    <artifactId>my-app</artifactId>
    <version>1</version>
    <relativePath>../my-app/pom.xml</relativePath>
  </parent>
  <modelVersion>4.0.0</modelVersion>
  <artifactId>my-module</artifactId>
</project>

這裡 my-module 繼承了 my-app 的 <groupId><version>,這樣也就實現了繼承。

POM 中多模組專案的聚合和繼承針對的都是以上兩種目錄結構的專案。

專案聚合

聚合與繼承相似,不同的是繼承方式配置的是子模組的 POM,而聚合方式配置的是父模組的 POM(即 pom.xml 檔案)。操作步驟如下

1. 將父模組 POMs 的 packaging 值設為 "pom"
2. 在父模組 POM 中指定子模組的路徑
  • 第一種結構 Example 1:
my-app
 |-- my-module
 |   `-- pom.xml
 `-- pom.xml

針對這種結構,我們在 my-app 模組(父模組)的 POM 檔案中新增<modules>元素進行配置

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1</version>
  <packaging>pom</packaging>

  <modules>
    <module>my-module</module>
  </modules>
</project>

注意,在聚合方式中,父模組的打包方式<packaging>發生了改變,這裡是pom而不再是war<module>元素中使用的是子模組相對於父模組的路徑。

通過這種配置方式,在 my-app 上執行的 Maven 命令也會在 my-module 上執行。

  • 第二種結構 Example 2:
.
 |-- my-module
 |   `-- pom.xml
 `-- my-app
     `-- pom.xml

參考第一種結構,我們使用了<module>元素中模組之間的相對路徑,那麼對於第二種結構,我們修改下相對路徑即可。

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1</version>
  <packaging>pom</packaging>

  <modules>
    <module>../my-module</module>
  </modules>
</project>

專案繼承和聚合的組合使用

首先說一下繼承和聚合使用的場景:
繼承:有多個 Maven 專案,它們具有相似的 POM 配置資訊。我們可以重構所有專案,將相似的配置資訊抽取出來,放到新建立的父專案裡,然後讓所有 Maven 專案繼承父專案,這樣就是繼承的用法。
聚合:有一組專案,它們同時編譯或執行,那我們可以建立一個父專案,將這組專案宣告為父專案的多個子模組,這樣的話,我們就只用編譯或執行父專案即可。這是聚合的使用場景。

我們在實際開發過程中,會組合使用繼承和聚合。比如說,我們需要開發一個專案,這個專案由多個模組組成,這些模組用到的 POM 配置資訊相似,而且模組之間會有依賴關係,某個模組依賴於另外一個模組才能正常執行。這樣情況我們就可以組合使用繼承和聚合,能大大的減少專案的配置和管理成本。

使用繼承和聚合,需要遵循3個規定:

1. 在每個子 POM 中指定它們的父 POM
2. 將父 POMs 打包方式設為 "pom"
3. 在父 POM 中指定子模組的路徑

我們使用第二種結構作為示例。第一種結構與其相似,去掉 <relativePath>即可。

my-app 專案中:

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1</version>
  <packaging>pom</packaging>

  <modules>
    <module>../my-module1</module>
    <module>../my-module2</module>
    <module>../my-module3</module>
  </modules>
</project>

my-module1 專案中:

<project>
  <parent>
    <groupId>com.mycompany.app</groupId>
    <artifactId>my-app</artifactId>
    <version>1</version>
    <relativePath>../my-app/pom.xml</relativePath>
  </parent>
  <modelVersion>4.0.0</modelVersion>
  <artifactId>my-module1</artifactId>
</project>

my-module2、my-module3 專案配置與 my-module1 相似,不列出。

實際開發過程中,多模組的管理方式可以是繼承和聚合的組合使用。我在之前建立的用於學習的專案,可以僅僅使用繼承。其中為了將 POM 配置資訊獨立出來,可以新建一個模組,這個模組只有 POM 配置資訊,其他的模組依賴這個模組,即可實現 Maven 依賴的複用。

專案中的變數

Maven 允許在 POM 中使用自定義的和預設的變數。自定義變數的方式:

<properties>
    <spring.version>4.3.6.RELEASE</spring.version>
</properties>

使用方式:

<version>${spring.version}</version>

實戰:多模組專案 POM 示例

專案模組組織關係:
專案有一個核心模組,提供了專案其他模組執行時的各種元件。依賴於這個核心模組,專案提供了 瀏覽器 和 App 兩種基礎服務後臺。在 瀏覽器 後臺上,構建一個 Demo 專案,用於展示專案開發成果。

使用 Maven 管理:
首先構建一個父模組,所有的模組都繼承這個父模組

parent-module:

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>big-project</groupId>
    <artifactId>parent-module</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <properties>
         <p.version>1.0-SNAPSHOT</p.version>
    </properties>
    ...

    <modules>
        <module>../core-module</module>
        <module>../browser-module</module>
        <module>../app-module</module>
        <module>../demo-module</module>
    </modules>
</project>

建好後,和其他模組的目錄結構關係如下:

.
 |-- parent-module
    `-- pom.xml
 |-- core-module
     `-- pom.xml
 |-- app-module
    `-- pom.xml
 |-- browser-module
     `-- pom.xml
 |-- demo-module
     `-- pom.xml

其他模組 POM 配置如下

core-module:

<project>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>core-module</artifactId>
    <parent>
        <groupId>big-project</groupId>
        <artifactId>parent-module</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../parent-module</relativePath>
    </parent>

    ...

</project>

app-module:

<project>
    <artifactId>app-module</artifactId>
    <parent>
        <groupId>big-project</groupId>
        <artifactId>parent-module</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../parent-module</relativePath>
    </parent>

    <dependencies>
        <dependency>
            <groupId>big-project</groupId>
            <artifactId>core-module</artifactId>
            <version>${p.version}</version>
        </dependency>

        ...

    </dependencies>
</project>

browser-module:

<project>
    <artifactId>browser-module</artifactId>
    <parent>
        <groupId>big-project</groupId>
        <artifactId>parent-module</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../parent-module</relativePath>
    </parent>

    <dependencies>
        <dependency>
            <groupId>big-project</groupId>
            <artifactId>core-module</artifactId>
            <version>${p.version}</version>
        </dependency>

        ...

    </dependencies>
</project>

demo-module:

<project>
    <artifactId>demo-module</artifactId>
    <parent>
        <groupId>big-project</groupId>
        <artifactId>parent-module</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../parent-module</relativePath>
    </parent>

    <dependencies>
        <dependency>
            <groupId>big-project</groupId>
            <artifactId>browser-module</artifactId>
            <version>${p.version}</version>
        </dependency>

        ...

    </dependencies>
</project>

在 parent-module 中,配置了多個 <module>元素,其他的模組也相應地配置了 <parent>資訊,這樣在編譯或執行 parent-module 時,其他模組也都進行了編譯或執行。
app-module 和 browser-module 均依賴於 core-module,均使用了 <dependency>來完成這個依賴。
demo-module 依賴於 browser-module,使用<dependency>來完成這個依賴。

參考資料:

相關推薦

Maven POM 檔案繼承Inheritance 聚合Aggregation- IDEA Eclipse 模組專案Maven 組織方法

Maven POM 檔案中的繼承和聚合(Inheritance & Aggregation) 之前在 IDEA 裡建了一個專案專門用來學習,每個知識點都建立一個相應的模組,方便學習和檢視。今天在建第二個模組的時候發現,這個模組很多的 Mave

Maven pom檔案屬性變數總結

1.內建屬性:${basedir}表示當前專案根目錄; ${version}表示當前專案版本。 2.POM屬性: ${project.artifactId} 等價於元素的值,個人理解,本質上每個標籤底層是通過物件的引用實現,也同樣存在繼承特性(僅僅是個人理解,供

Maven POM檔案依賴與外掛的配置

POM(Project Object Model)是 Maven 工程的工作基礎,以 pom.xml 的形式存在於專案中,在這裡配置構建工程的詳細資訊。它為大多數專案都預先配置了一些預設值,如構建目錄 build,原始碼目錄 src/main/java,測試原始

Springboot整合dubbo構建maven模組專案- 專案建立pom.xmljar包配置

       以前一直用Spring作為容器構建專案,但是看到Spring官網一直在推Springboot,最重要的是Springboot確實避免自己尋找多個jar包(大多數情況下,可能自己都不記得該引入哪些jar包)和jar包之間衝突的問題,同時省掉了在整合其他框架時候

springboot模組專案,引用子專案的mapper的xml檔案

springboot多模組專案,引用子專案的mapper中的xml檔案,一直引用不到, 提示: Caused by: org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): utopi

原創超詳細一步一步在eclipse配置Struts2環境,無基礎也能看懂

    (原創)超詳細一步一步在eclipse中配置Struts2環境,無基礎也能看懂  1. 在官網https://struts.apache.org下載Struts2,建議下載2.3系列版本。從圖中可以看出,既可以分開下載子檔案,又可以一次全部下載。 這裡我後

史上最全的Maven Pom檔案標籤詳解

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="

Spring SpringMVC Maven pom檔案

<dependencies> <!--Spring支援包--> <!-- https://mvnrepository.com/artifact/commons-l

Maven實戰——模組專案POM重構

在本專欄的上一篇文章POM重構之增還是刪中,我們討論了一些簡單實用的POM重構技巧,包括重構的前提——持續整合,以及如何通過新增或者刪除內容來提高POM的可讀性和構建的穩定性。但在實際的專案中,這些技巧還是不夠的,特別值得一提的是,實際的Maven專案基本都是多模組的,如果僅

UML類之間的幾種關係,關聯association聚合Aggregation,組合Composition

類之間可能存在以下幾種關係:關聯(association)、依賴(dependency)、聚合(Aggregation,也有的稱聚集)、組合(Composition)、泛化(generalization,也有的稱繼承)、實現(Realization)。 關聯是指兩個類之間存在某種特定的對應關係,例如客戶和訂

Maven學習總結——IDEA使用Maven構建模組專案

  在平時的Javaweb專案開發中為了便於後期的維護,我們一般會進行分層開發,最常見的就是分為domain(域模型層)、dao(資料庫訪問層)、service(業務邏輯層)、web(表現層),這樣分層之後,各個層之間的職責會比較明確,後期維護起來也相對比較容易,今天我們就是使用Maven來構建以上的各個層

IDEA建立Web聚合專案(Maven模組專案)

1、建立parent專案 2、建立子模組 3、這樣一個project就建立好了,刪除沒有用的src 4、當前結構 5、這個時候建立的不管是child1還是child2都是普通的Java專案,而不是JavaWeb專案,在一個JavaWeb專案中,我們的模組可能分為

IntelliJ IDEA建立Web聚合專案(Maven模組專案)

Eclipse用多了,IntelliJ中建立Maven聚合專案可能有小夥伴還不太熟悉,我們今天就來看看。 IntelliJ中建立普通的Java聚合專案相對來說比較容易,不會涉及到web操作,涉及到web的話會有一點點麻煩。我們來一步一步看下。 環境:In

如何在Eclipse/Myeclipse/Scala IDEA for Eclipse 正確刪除已經下載過的外掛圖文詳解

  不多說,直接上乾貨!   見 第一步 :在選單欄中,找到help-------install new software  第二步,需要注意了,注意看圖。紅色區域標註的already installed?  點選進去,找到你需要要刪除的軟體,

Maven權威指南模組專案構建及POM優化

  在《Maven權威指南》部分I中,第6、7章介紹了多模組專案及多模組企業級專案的構建思想。對於多模組的情況,無論是簡單的或是企業級的,對於POM來說,重點就是分析處理好父POM與子POM之間的關係,包括依賴管理(DependencyManagement)、外掛管理(Plu

IntelliJ IDEA建立Web聚合專案(Maven模組專案)詳細版本!!

Eclipse用多了,IntelliJ中建立Maven聚合專案可能有小夥伴還不太熟悉,我們今天就來看看。 IntelliJ中建立普通的Java聚合專案相對來說比較容易,不會涉及到web操作,涉及到web的話會有一點點麻煩。我們來一步一步看下。環境:IntelliJ IDEA

Maven模組專案應用maven-tomcat-plugin熱部署

我這個專案是用maven管理的一個多模組的專案,大概結構是 aaa      -Business      -Core      -Framework      -Web aaa是pom專案,Web是war專案,其它的是jar 一開始我是在Web裡面配置了tomcat的

maven pom檔案詳解

 1<project xmlns="http://maven.apache.org/POM/4.0.0 "   2   3    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance "   4   5  

Maven POM檔案模組以及依賴關係

一、POM.XML 1、ProjectObject Model:專案物件模型 2、基本項: project:pom.xml的頂級元素。groupId:指出建立這個工程的組織或團隊的唯一標識。plugins:外掛。artifactId:基本名稱。packaging:型別(如J

idea(二)--idea建立模組專案maven模組開發

一、idea中建立多模組專案(多工程同時開發) 熟悉eclipse、myeclipse的人都知道,eclipse、myeclipse中都有工作的空間(workspace)的概念,一個workspace中可以建立多個project,即可同時開啟多個專案進行開發。然而,遺憾的是