Maven項目之間關係介紹

Maven項目之間的關係

依賴關係

單純的項目A中需要項目B中的資源,將項目B打成Jar包被A依賴,此時項目A直接調用項目B中資源即可。

項目A和項目B此時形成最基本的依賴關係。

繼承關係

需要場景:
如果多個子項目中使用的是相同的依賴或插件,此時我們可以把相同的配置抽取到一個父項目中,進行統一的管理,保持一致性。所以繼承關係此時顯得比較重要,在java中,繼承體現在代碼功能上,而maven中的繼承則體現在pom.xml,跟功能代碼沒有關係,當項目A繼承了項目B,則項目A擁有了項目B的pom.xml文件中所有依賴。當然繼承中也不同的用法和不同的場景。

我們在同級目錄創建01_parent、02_child、03_child,一個父項目,兩個子項目

01_parent的pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="//maven.apache.org/POM/4.0.0"
       xmlns:xsi="//www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="//maven.apache.org/POM/4.0.0 //maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <!-- 將其作為maven項目的父項目,統一管理子項目的公共依賴 -->
  <groupId>org.example</groupId>
  <artifactId>01_parent</artifactId>
  <version>1.0-SNAPSHOT</version>
  <!-- 父項目的專有打包方式,該種方式,本項目不會被打包成 jar 或 war ,項目里 src 目錄下代碼無效(可刪除), pom.xml 有效,只是作為其它項目的父項目使用. -->
  <packaging>pom</packaging>
  <properties>
      <spring-version>5.2.9.RELEASE</spring-version>
  </properties>

  <dependencies>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>${spring-version}</version>
      </dependency>
      <!--配置webmvc-->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-webmvc</artifactId>
          <version>${spring-version}</version>
      </dependency>
      <dependency>
          <groupId>log4j</groupId>
          <artifactId>log4j</artifactId>
          <version>1.2.17</version>
      </dependency>
      <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.11</version>
          <scope>test</scope>
      </dependency>
  </dependencies>
</project>

02_child的pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="//maven.apache.org/POM/4.0.0"
         xmlns:xsi="//www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="//maven.apache.org/POM/4.0.0 //maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.example</groupId>
        <artifactId>01_parent</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

<!-- <groupId>org.example</groupId> 如果子項目和父項目在同一級目錄,使用parent標籤表明了父項目坐標後,子項目的groupId可以省去 -->
    <artifactId>02_child</artifactId>
    <version>1.0-SNAPSHOT</version>
</project>

03_child的pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="//maven.apache.org/POM/4.0.0"
         xmlns:xsi="//www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="//maven.apache.org/POM/4.0.0 //maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.example</groupId>
        <artifactId>01_parent</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>03_child</artifactId>
    <version>1.0-SNAPSHOT</version>
</project>

然後我們看看maven項目之間的關係:

20210915102806

我們很明顯的看到,兩個子項目都成功的擁有了父項目的依賴。maven的基本繼承關係就弄完了。

但是實際開發中,我們可能有多個功能不同得子項目,父項目中的依賴並不是每一個子項目都必須全部需要的。這個時候如果子項目擁有了父項目全部依賴就有點說不過去了,甚至可能產生jar包衝突。

這裡我們可以使用<dependencyManagement>標籤來解決我們上述的問題,這個標籤的作用其實相當於一個對所依賴 jar 包進行版本管理的管理器.( dependencyManagement 里只是聲明依賴,並不實現引入)

這樣一來,父項目就像超市,子項目就像客戶,父項目將部分不是基本的依賴放入其中,子項目需要就聲明即可,不需要的話父項目也不會強人所難。

01_parent的pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="//maven.apache.org/POM/4.0.0"
       xmlns:xsi="//www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="//maven.apache.org/POM/4.0.0 //maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <!-- 將其作為maven項目的父項目,統一管理子項目的公共依賴 -->
  <groupId>org.example</groupId>
  <artifactId>01_parent</artifactId>
  <version>1.0-SNAPSHOT</version>
  <!-- 父項目的專有打包方式,該種方式,本項目不會被打包成 jar 或 war ,項目里 src 目錄下代碼無效(可刪除), pom.xml 有效,只是作為其它項目的父項目使用. -->
  <packaging>pom</packaging>
  <properties>
      <spring-version>5.2.9.RELEASE</spring-version>
  </properties>

  <dependencies>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>${spring-version}</version>
      </dependency>
      <!--配置webmvc-->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-webmvc</artifactId>
          <version>${spring-version}</version>
      </dependency>
      <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.11</version>
          <scope>test</scope>
      </dependency>
  </dependencies>

  <!--dependencyManagement 標籤中聲明的依賴,只是作為一個 jar 包統一管理的管理器,實際上該標籤中聲明的依賴不會被引入-->
  <dependencyManagement>
      <dependencies>
          <dependency>
              <groupId>log4j</groupId>
              <artifactId>log4j</artifactId>
              <version>1.2.17</version>
          </dependency>

          <dependency>
              <groupId>commons-logging</groupId>
              <artifactId>commons-logging</artifactId>
              <version>1.0</version>
          </dependency>
      </dependencies>
  </dependencyManagement>
</project>

在01_parent這個「超市」中添加了log4j和commons-logging的兩個依賴供子項目選擇。

此時02_child需要log4j這個依賴:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="//maven.apache.org/POM/4.0.0"
         xmlns:xsi="//www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="//maven.apache.org/POM/4.0.0 //maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.example</groupId>
        <artifactId>01_parent</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

<!-- <groupId>org.example</groupId> 如果子項目和父項目在同一級目錄,使用parent標籤表明了父項目坐標後,子項目的groupId可以省去 -->
    <artifactId>02_child</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
        </dependency>
    </dependencies>
</project>

03_child需要commons-logging這個依賴:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="//maven.apache.org/POM/4.0.0"
         xmlns:xsi="//www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="//maven.apache.org/POM/4.0.0 //maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.example</groupId>
        <artifactId>01_parent</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>03_child</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
        </dependency>
    </dependencies>
</project>

看maven項目之間的依賴:

20210915104321

此時02_child沒有了commons-logging,03_child沒有了log4j,我們已經解決了這個問題。

如果子項目使用的依賴不是父項目的版本,需要在子項目的pom中標明依賴的版本,否則默認使用的是父項目管理的版本。

其實我們這個問題主要是學習<dependencyManagement>這一標籤在父項目中的作用

打包

此時我們對02_child進行打包會報錯,具體原因是:

Non-resolvable parent POM for org.example:02_child:1.0-SNAPSHOT: Could not find artifact org.example:01_parent:pom:1.0-SNAPSHOT and ‘parent.relativePath’ points at wrong local POM @ line 7, column 13@

說子項目解析不了父項目的POM文件,parent.relativePath錯誤。其實,我們在子類的parent標籤中還要加一個<relativePath>標籤,來指明父項目中POM的相對物理路徑,這樣子項目打包的時候,maven才能工具標籤找到父項目的POM地址,不然也不知道子項目的引用從哪來。

項目報錯:

  • 子項目打包出錯:Invalid packaging for parent POM com.cloud:DemoName:1.0-SNAPSHOT, must be 「pom「 but is 「jar「。

    我們必須在父項目中pom指定打包格式為POM:<packaging>pom</packaging>

  • Could not find artifact com.cloud:DemoName:pom:1.0-SNAPSHOT

    子項目打包前必須先打包父項目

聚合關係

聚合本身沒有實質的內容,隨着程序的發展,項目也會越來越大,功能越來越多,開發人員往往會將其劃分模塊進行開發,功能清晰,設計清晰。maven的聚合特性就是將多個模塊聚合在一起構建。並且聚合是建立在繼承關係上,父項目的作用除了統一管理子項目的依賴,還做最後統一構建所有子模塊,實現一次構建多個項目!

此處做個比喻,有一天我們被要求製作一個「強大」的機器,機械人靠着很多零件組裝,團隊有4個人,一個管理員,三個開發人員,管理員將其工具包分成三個局部零件交給我們開發,我們每人一個不同的零件開發模塊,並在管理員下進行開發。我們開發時,如果零件模塊之間沒有互相依賴的關係可以並行開發,如果有單向依賴關係那就得看具體需求了。

當我們開發完成後統一交給管理員對我們的局部零件進行組裝,最後的結果就是管理員(Maven)統一聚合項目下所有子模塊成為最終項目成果。

代碼就不演示了,我使用的是MVC分成4個模塊(pojo,mapper,serivce,controller),單項依賴感覺不能講的很清楚,其實自己對聚合關係也只是一知半解,了解基本,還沒有進行實質的開發。體會不到聚合關係帶來的便利(才學疏淺),要了解詳情就要去看別的博客了。

小結

本次是對Maven項目之間三大關係的介紹:

  • 最基本的依賴關係:A依賴B
  • 繼承關係:B和C的公共依賴、部分依賴被A統一管理
  • 聚合關係:B、C功能模塊開發完,被A統一進行聚合成完整的功能或項目。(聚合關係建立在繼承關係上)
Tags: