Java開發學習(三十)----Maven聚合和繼承解析

2022-09-06 12:01:40

一、聚合

  • 分模組開發後,需要將這四個專案都安裝到本地倉庫,目前我們只能通過專案Maven面板的install來安裝,並且需要安裝四個,如果我們的專案足夠多,那麼一個個安裝起來還是比較麻煩的

  • 如果四個專案都已經安裝成功,當ssm_pojo發生變化後,我們就得將ssm_pojo重新安裝到maven倉庫,但是為了確保我們對ssm_pojo的修改不會影響到其他專案模組,我們需要對所有的模組進行重新編譯,那又需要將所有的模組再來一遍

專案少的話還好,但是如果專案多的話,一個個操作專案就容易出現漏掉或重複操作的問題,所以我們就想能不能抽取一個專案,把所有的專案管理起來,以後我們要想操作這些專案,只需要操作這一個專案,其他所有的專案都走一樣的流程,這個不就很省事省力。

這就用到了我們接下來的聚合

  • 所謂聚合:將多個模組組織成一個整體,同時進行專案構建的過程稱為聚合

  • 聚合工程:通常是一個不具有業務功能的"空"工程(有且僅有一個pom檔案)

  • 作用:使用聚合工程可以將多個工程編組,通過對聚合工程進行構建,實現對所包含的模組進行同步構建

    • 當工程中某個模組發生更新(變更)時,必須保障工程中與已更新模組關聯的模組同步更新,此時可以使用聚合工程來解決批次模組同步構建的問題。

關於聚合具體的實現步驟為:

步驟1:建立一個空的maven專案

步驟2:將專案的打包方式改為pom

<?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>

    <groupId>com.itheima</groupId>
    <artifactId>maven_01_parent</artifactId>
    <version>1.0-RELEASE</version>
    <packaging>pom</packaging>
    
</project>

說明:專案的packaging打包方式,我們接觸到的有三種,分別是

  • jar:預設情況,說明該專案為java專案

  • war:說明該專案為web專案

  • pom:說明該專案為聚合或繼承(後面會講)專案

步驟3: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>

    <groupId>com.itheima</groupId>
    <artifactId>maven_01_parent</artifactId>
    <version>1.0-RELEASE</version>
    <packaging>pom</packaging>
    
    <!--設定管理的模組名稱  例如存在如下模組-->
    <modules>
        <module>../maven_02_ssm</module>
        <module>../maven_03_pojo</module>
        <module>../maven_04_dao</module>
    </modules>
</project>

步驟4:使用聚合統一管理專案

測試發現,當maven_01_parentcompile被點選後,所有被其管理的專案都會被執行編譯操作。這就是聚合工程的作用。

說明:聚合工程管理的專案在進行執行的時候,會按照專案與專案之間的依賴關係來自動決定執行的順序 ,按照倒序進行構建,和modules裡面的設定的順序無關。

二、繼承

我們已經完成了使用聚合工程去管理專案,聚合工程進行某一個構建操作,其他被其管理的專案也會執行相同的構建操作。那麼接下來,我們再來分析下,多模組開發存在的另外一個問題,重複設定的問題,我們先來看張圖:

  • spring-webmvcspring-jdbc在三個專案模組中都有出現,這樣就出現了重複的內容

  • spring-test只在ssm_crm和ssm_goods中出現,而在ssm_order中沒有,這裡是部分重複的內容

  • 我們使用的spring版本目前是5.2.10.RELEASE,假如後期要想升級spring版本,所有跟Spring相關jar包都得被修改,涉及到的專案越多,維護成本越高

面對上面的這些問題,我們就得用到接下來的繼承

  • 所謂繼承:描述的是兩個工程間的關係,與java中的繼承相似,子工程可以繼承父工程中的設定資訊,常見於依賴關係的繼承。

  • 作用:

    • 簡化設定

    • 減少版本衝突

接下來,我們到程式中去看看繼承該如何實現?

步驟1:建立一個空的Maven專案並將其打包方式設定為pom

因為這一步和前面maven建立聚合工程的方式是一摸一樣,所以我們可以單獨建立一個新的工程,也可以直接和聚合公用一個工程。實際開發中,聚合和繼承一般也都放在同一個專案中,但是這兩個的功能是不一樣的。

步驟2:在子專案中設定其父工程

分別在maven_02_ssm,maven_03_pojo,maven_04_dao的pom.xml中新增其父專案為maven_01_parent

<!--設定當前工程繼承自parent工程-->
<parent>
    <groupId>com.itheima</groupId>
    <artifactId>maven_01_parent</artifactId>
    <version>1.0-RELEASE</version>
    <!--設定父專案pom.xml位置路徑-->
    <relativePath>../maven_01_parent/pom.xml</relativePath>
</parent>

步驟3:優化子專案共有依賴匯入問題

  1. 將子專案共同使用的jar包都抽取出來,維護在父專案的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>

    <groupId>com.itheima</groupId>
    <artifactId>maven_01_parent</artifactId>
    <version>1.0-RELEASE</version>
    <packaging>pom</packaging>
    
    <!--設定管理的模組名稱-->
    <modules>
        <module>../maven_02_ssm</module>
        <module>../maven_03_pojo</module>
        <module>../maven_04_dao</module>
    </modules>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.0</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.16</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.0</version>
        </dependency>
    </dependencies>
</project>
  1. 刪除子專案中已經被抽取到父專案的pom.xml中的jar包,如在maven_02_ssm的pom.xml中將已經出現在父專案的jar包刪除掉

<?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>

  <groupId>com.itheima</groupId>
  <artifactId>maven_02_ssm</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <!--設定當前工程繼承自parent工程-->
  <parent>
    <groupId>com.itheima</groupId>
    <artifactId>maven_01_parent</artifactId>
    <version>1.0-RELEASE</version>
    <relativePath>../maven_01_parent/pom.xml</relativePath>
  </parent>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.tomcat.maven</groupId>
        <artifactId>tomcat7-maven-plugin</artifactId>
        <version>2.1</version>
        <configuration>
          <port>80</port>
          <path>/</path>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

刪除完後,你會發現父專案中有依賴對應的jar包,子專案雖然已經將重複的依賴刪除掉了,但是重新整理的時候,子專案中所需要的jar包依然存在。

當專案的<parent>標籤被移除掉,會發現多出來的jar包依賴也會隨之消失。

  1. maven_04_dao專案的pom.xml中的所有依賴刪除,然後新增上maven_01_parent的父專案座標

<?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>

    <groupId>com.itheima</groupId>
    <artifactId>maven_04_dao</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!--設定當前工程繼承自parent工程-->
    <parent>
        <groupId>com.itheima</groupId>
        <artifactId>maven_01_parent</artifactId>
        <version>1.0-RELEASE</version>
        <relativePath>../maven_01_parent/pom.xml</relativePath>
    </parent>
</project>

重新整理並檢視Maven的面板,會發現maven_04_dao同樣引入了父專案中的所有依賴。

這樣我們就可以解決剛才提到的第一個問題,將子專案中的公共jar包抽取到父工程中進行統一新增依賴,這樣做的可以簡化設定,並且當父工程中所依賴的jar包版本發生變化,所有子專案中對應的jar包版本也會跟著更新。

步驟4:優化子專案依賴版本問題

如果把所有用到的jar包都管理在父專案的pom.xml,看上去更簡單些,但是這樣就會導致有很多專案引入了過多自己不需要的jar包。如上面看到的這張圖:

如果把所有的依賴都放在了父工程中進行統一維護,例如ssm_crm,ssm_goods,ssm_order都繼承至ssm_parent,並且ssm_parent裡面包含了spring-webmvc、spring-jdbc、spring-test等依賴,那這樣就會導致ssm_order專案中多引入了spring-test的jar包(但其實是不需要),如果這樣的jar包過多的話,對於ssm_order來說也是一種"負擔"。

那針對於這種部分專案有的jar包,我們該如何管理優化呢?

  1. 在父工程mavne_01_parent的pom.xml來定義依賴管理

<!--定義依賴管理-->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
  1. 將maven_02_ssm的pom.xml中的junit依賴刪除掉,重新整理Maven

重新整理完會發現,在maven_02_ssm專案中的junit依賴並沒有出現,所以我們得到一個結論:<dependencyManagement>標籤不真正引入jar包,而是設定可供子專案選擇的jar包依賴。子專案要想使用它所提供的這些jar包,需要自己新增依賴,並且不需要指定<version>

  1. 在maven_02_ssm的pom.xml新增junit的依賴

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <scope>test</scope>
</dependency>

注意:這裡就不需要新增版本了,這樣做的好處就是當父工程dependencyManagement標籤中的版本發生變化後,子專案中的依賴版本也會跟著發生變化

maven_02_ssm這個專案中的junit版本就會跟隨著父專案中的標籤dependencyManagement中junit的版本發生變化而變化。不需要junit的專案就不需要新增對應的依賴即可。

總結來說,繼承可以幫助做兩件事

  • 將所有專案公共的jar包依賴提取到父工程的pom.xml中,子專案就可以不用重複編寫,簡化開發

  • 將所有專案的jar包設定到父工程的dependencyManagement標籤下,實現版本管理,方便維護

    • dependencyManagement標籤不真正引入jar包,只是管理jar包的版本

    • 子專案在引入的時候,只需要指定groupId和artifactId,不需要加version

    • 當dependencyManagement標籤中jar包版本發生變化,所有子專案中有用到該jar包的地方對應的版本會自動隨之更新

三、聚合與繼承的區別

3.1 聚合與繼承的區別

兩種之間的作用:

  • 聚合用於快速構建專案,對專案進行管理

  • 繼承用於快速設定和管理子專案中所使用jar包的版本

聚合和繼承的相同點:

  • 聚合與繼承的pom.xml檔案打包方式均為pom,可以將兩種關係製作到同一個pom檔案中

  • 聚合與繼承均屬於設計型模組,並無實際的模組內容

聚合和繼承的不同點:

  • 聚合是在當前模組中設定關係,聚合可以感知到參與聚合的模組有哪些

  • 繼承是在子模組中設定關係,父模組無法感知哪些子模組繼承了自己