[這可能是最好的Spring教程!]Maven的模組管理——如何拆分大專案並且用parent繼承保證程式碼的簡潔性

ENchantEd丨發表於2024-11-13

問題的提出

在軟體開發中,我們為了減少軟體的複雜度,是不會把所有的功能都塞進一個模組之中的,塞在一個模組之中對於軟體的管理無疑是極其困難且複雜的。所以把一個專案拆分為模組無疑是一個好方法

                        ┌ ─ ─ ─ ─ ─ ─ ┐
                          ┌─────────┐
                        │ │Module A │ │
                          └─────────┘
┌──────────────┐ split  │ ┌─────────┐ │
│Single Project│───────▶  │Module B │
└──────────────┘        │ └─────────┘ │
                          ┌─────────┐
                        │ │Module C │ │
                          └─────────┘
                        └ ─ ─ ─ ─ ─ ─ ┘

對於Maven工程來說,原來是一個大專案:

single-project
├── pom.xml
└── src

現在可以分拆成3個模組:

multiple-projects
├── module-a
│   ├── pom.xml
│   └── src
├── module-b
│   ├── pom.xml
│   └── src
└── module-c
    ├── pom.xml
    └── src

我們能看到的是每一個模組都有屬於自己的pom.xml,然後模組A的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.itranswarp.learnjava</groupId>
    <artifactId>module-a</artifactId>
    <version>1.0</version>
    <packaging>jar</packaging>

    <name>module-a</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <java.version>11</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.28</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>5.5.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

之後B的pom.xml也大同小異,只用把<artifactId>module-a</artifactId><name>module-a</name> 改為自己的就行。這個時候我們就會發現一個很麻煩的事,我們很多地方都是一樣的,但是每一個模組的pom都需要我們重複宣告出來,那我們能不能用像物件那樣繼承下來,這樣就不用重複宣告瞭呢?Maven無疑是有這樣的功能的

問題的解決

簡化後的結構

我們現在看看簡化後的模組結構式如何的

multiple-project
├── pom.xml
├── parent
│   └── pom.xml
├── module-a
│   ├── pom.xml
│   └── src
├── module-b
│   ├── pom.xml
│   └── src
└── module-c
    ├── pom.xml
    └── src

與之對比的是根目錄多了一個pom,然後多加了一個"模組"parent,裡面沒有程式碼src,只有一個裸的pom。

看了對比之後我們一個一個講是怎麼修改的,結構又是怎麼樣的

修改細則

parent

我們先來看parent裡面的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>

    <groupId>com.itranswarp.learnjava</groupId>
    <artifactId>parent</artifactId>
    <version>1.0</version>
    <packaging>pom</packaging>

    <name>parent</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <java.version>11</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.28</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>5.5.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

我們能發現的是,對於之前的模組A修改其實也不多,修改的分別是<artifactId>parent</artifactId> <packaging>pom</packaging> <name>parent</name>

這裡我們著重講一下<packaging>pom</packaging>,首先我們先明白<packaging>這個標籤代表了什麼,

<packaging>這個標籤他表示打包的方式,常見的值為jar(Java庫)、war(Web應用)、pom(父專案)等。這個地方parentpackaging設定為pom,因為它不生成任何可執行的JAR檔案,僅提供配置和依賴管理。

其他模組的簡化思路

看完了parent的程式碼之後我們就慢慢地去理清簡化的思路

編碼與java版本配置

首當其衝的無疑就是這個部分,這個地方模組AB都是需要的,而且都是一樣的,那麼這個元素就是可以被繼承的,也就是是可以省略的

<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <java.version>11</java.version>
    </properties>
公共依賴項

其次就是AB都需要的依賴項如slf4j-apilogback-classicjunit-jupiter-engine,以及作用域的設定

<dependencies>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.28</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>5.5.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

修改後的模組A的pom

我們再開看看修改後模組A的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.itranswarp.learnjava</groupId>
        <artifactId>parent</artifactId>
        <version>1.0</version>
        <relativePath>../parent/pom.xml</relativePath>
    </parent>

    <artifactId>module-a</artifactId>
    <packaging>jar</packaging>
    <name>module-a</name>
</project>

不得不說有了parent之後,整個模組都變得簡潔了起來

在設定好parent模組後,我們只需要引用parent作為其他模組的父模組。

首先透過<parent>標籤引用parent模組

    <parent>
        <groupId>com.itranswarp.learnjava</groupId>
        <artifactId>parent</artifactId>
        <version>1.0</version>
        <relativePath>../parent/pom.xml</relativePath>
    </parent>

有了這些之後就相當於繼承了parent裡面的元素了。

之後我們再匯入自己獨有的元素就基本上完成了對此模組的配置

<artifactId>module-a</artifactId>
<packaging>jar</packaging>
<name>module-a</name>

繼承parent模組後,模組A和模組B的pom.xml檔案已經大幅簡化。所有公共配置項,如UTF-8編碼、Java編譯版本、以及日誌和測試的依賴庫,均已在parent中配置好。這樣,模組A和模組B僅需保留獨有的內容,簡化了配置並降低了維護成本。

相互的引用

如果模組A需要引用模組B的程式碼,可以在模組A的<dependencies>中增加對模組B的依賴項,如下:

<dependencies>
    <dependency>
        <groupId>com.itranswarp.learnjava</groupId>
        <artifactId>module-b</artifactId>
        <version>1.0</version>
    </dependency>
</dependencies>

透過這一配置,Maven會在構建模組A時自動獲取模組B生成的JAR檔案,使得模組A可以使用模組B中的程式碼和功能。

根目錄pom的配置

最後的最後,我們配置最後根目錄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/maven-v4_0_0.xsd">

    <modelVersion>4.0.0</modelVersion>
    <groupId>com.itranswarp.learnjava</groupId>
    <artifactId>build</artifactId>
    <version>1.0</version>
    <packaging>pom</packaging>
    <name>build</name>

    <modules>
        <module>parent</module>
        <module>module-a</module>
        <module>module-b</module>
        <module>module-c</module>
    </modules>
</project>

這樣,在根目錄執行mvn clean package時,Maven根據根目錄的pom.xml找到包括parent在內的共4個<module>,一次性全部編譯。

這可能是最好的Spring教程!

感謝您看到這裡 這可能是最好的Spring教程系列 更多的文章可以到這檢視這可能是最好的Spring教程!即便無基礎也能看懂的入門Spring,仍在持續更新。,我還在荔枝更新出最詳細的Spring教程

相關文章