Maven專案之間關係介紹

CN_DADA發表於2021-09-18

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="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>
  <!-- 將其作為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="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>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="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>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="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>
  <!-- 將其作為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="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>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="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>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統一進行聚合成完整的功能或專案。(聚合關係建立在繼承關係上)

相關文章