Maven依賴管理

廢物大師兄發表於2023-11-29

1.  依賴管理

依賴管理,可以將有關依賴項的所有資訊放在共同的POM中,並對子POM中的工件進行更簡單的引用。舉個例子:

父POM

<project>
    ......
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>group-a</groupId>
                <artifactId>artifact-a</artifactId>
                <version>1.0</version>
                <exclusions>
                    <exclusion>
                        <groupId>group-c</groupId>
                        <artifactId>excluded-artifact</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>group-c</groupId>
                <artifactId>artifact-b</artifactId>
                <version>1.0</version>
                <type>war</type>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <groupId>group-a</groupId>
                <artifactId>artifact-b</artifactId>
                <version>1.0</version>
                <type>bar</type>
                <scope>runtime</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    ......
</project>

兩個子POM

<project>
    ...
    <dependencies>
        <dependency>
            <groupId>group-a</groupId>
            <artifactId>artifact-a</artifactId>
        </dependency>

        <dependency>
            <groupId>group-a</groupId>
            <artifactId>artifact-b</artifactId>
            <!-- This is not a jar dependency, so we must specify type. -->
            <type>bar</type>
        </dependency>
    </dependencies>
</project>


<project>
    ...
    <dependencies>
        <dependency>
            <groupId>group-c</groupId>
            <artifactId>artifact-b</artifactId>
            <!-- This is not a jar dependency, so we must specify type. -->
            <type>war</type>
        </dependency>

        <dependency>
            <groupId>group-a</groupId>
            <artifactId>artifact-b</artifactId>
            <!-- This is not a jar dependency, so we must specify type. -->
            <type>bar</type>
        </dependency>
    </dependencies>
</project>

在<dependencyManagement>區域,實際上是根據{groupId, artifactId, type, classifier}來進行依賴匹配的。自從<type>欄位的預設值是jar以後,最簡單的標識只需要設定{groupId, artifactId}即可。

依賴管理的另一個重要的作用是統一管理(控制)依賴的版本。這一點不再贅述。

2.  匯入依賴

依賴可以繼承,但是目前只支援單繼承,可以透過“import”的方式從其它POM中匯入依賴。

下面的例子,Z匯入了X和Y管理的依賴。

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>maven</groupId>
    <artifactId>Z</artifactId>
    <packaging>pom</packaging>
    <version>1.0</version>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>maven</groupId>
                <artifactId>X</artifactId>
                <version>1.0</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>maven</groupId>
                <artifactId>Y</artifactId>
                <version>1.0</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

舉個例子

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.example</groupId>
        <artifactId>demo-parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo001</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.7.11</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

3.  版本管理外掛

https://www.mojohaus.org/versions/versions-maven-plugin/index.html

versions外掛用於管理、模組、依賴和外掛的版。該外掛有很多目標,為了統一管理父子專案版本號,我們這裡只用其中三個。

操作很簡單,首先,在父工程中引入versions外掛

<!-- 父POM中增加外掛 -->
<build>
    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>versions-maven-plugin</artifactId>
            <version>2.16.2</version>
            <configuration>
                <generateBackupPoms>false</generateBackupPoms>
            </configuration>
        </plugin>
    </plugins>
</build>

然後,更新父工程的版本號

mvn versions:set -DnewVersion="2.0.0-SNAPSHOT" //更新整個專案版本

 接著,把子模組的版本更新成父工程的版本號

mvn versions:update-child-modules

 最後提交

mvn versions:commit

4.  BOM

對於一個專案來說,使用“庫”中的一個或多個構件是相當常見的。為了使專案中使用的構件的版本與庫中分發的版本保持同步。我們可以建立一個“物料清單”(BOM)以供其它專案使用。

簡單的來講,就是多個專案都需要依賴某些包時,為了方便管理版本,使得多個專案中引用的某個包的版本保持一致,這個時候我們就定義一個“庫”,在這個庫中統一定義包的版本,使用的時候只需要匯入這個庫即可。

舉個例子:

定義一個庫(其實就是一個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.test</groupId>
    <artifactId>mytest-bom</artifactId>
    <version>1.0.0</version>
    <packaging>pom</packaging>
    <properties>
        <project1Version>1.0.0</project1Version>
        <project2Version>1.0.0</project2Version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.test</groupId>
                <artifactId>project1</artifactId>
                <version>${project1Version}</version>
            </dependency>
            <dependency>
                <groupId>com.test</groupId>
                <artifactId>project2</artifactId>
                <version>${project2Version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

然後,定義兩個專案project1和project2

<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.test</groupId>
        <artifactId>mytest-bom</artifactId>
        <version>1.0.0</version>
    </parent>

    <groupId>com.test</groupId>
    <artifactId>parent</artifactId>
    <version>1.0.0</version>
    <packaging>pom</packaging>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.apache.logging.log4j</groupId>
                <artifactId>log4j-core</artifactId>
                <version>2.22.0</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>

project1

<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.test</groupId>
        <artifactId>parent</artifactId>
        <version>1.0.0</version>
    </parent>
    <groupId>com.test</groupId>
    <artifactId>project1</artifactId>
    <version>${project1Version}</version>
    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
        </dependency>
    </dependencies>
</project>

project2

<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.test</groupId>
        <artifactId>parent</artifactId>
        <version>1.0.0</version>
    </parent>
    <groupId>com.test</groupId>
    <artifactId>project2</artifactId>
    <version>${project2Version}</version>
    <packaging>jar</packaging>
</project>

最後,在其它專案中引用project1和project2

<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.test</groupId>
	<artifactId>use</artifactId>
	<version>1.0.0</version>
	<packaging>jar</packaging>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>com.test</groupId>
				<artifactId>mytest-bom</artifactId>
				<version>1.0.0</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<dependencies>
		<dependency>
			<groupId>com.test</groupId>
			<artifactId>project1</artifactId>
		</dependency>
		<dependency>
			<groupId>com.test</groupId>
			<artifactId>project2</artifactId>
		</dependency>
	</dependencies>
</project>

可以看到,使用的時候,直接匯入這個POM,然後按需引用

核心就是在一個公共的pom中定義包的版本和依賴管理,然後在使用的時候匯入公共pom

假設現在在做一個專案,其中有兩個子專案,在cjs-store-service中需要引用cjs-workflow-provider-api

先定義一個公共的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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>cjs-dependencies-bom</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <properties>
        <store.version>0.0.4-SNAPSHOT</store.version>
        <workflow.version>0.0.3-SNAPSHOT</workflow.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.example</groupId>
                <artifactId>cjs-store-provider-api</artifactId>
                <version>${store.version}</version>
            </dependency>
            <dependency>
                <groupId>com.example</groupId>
                <artifactId>cjs-workflow-provider-api</artifactId>
                <version>${workflow.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>

專案中引用

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.example</groupId>
        <artifactId>cjs-store</artifactId>
        <version>0.0.4-SNATHOST</version>
    </parent>
    <groupId>com.example</groupId>
    <artifactId>cjs-store-service</artifactId>
    <version>0.0.4-SNATHOST</version>
    
    <dependencies>
        <dependency>
            <groupId>com.example</groupId>
            <artifactId>cjs-store-dto</artifactId>
            <version>${project.parent.version}</version>
        </dependency>
        <dependency>
            <groupId>com.example</groupId>
            <artifactId>cjs-workflow-provider-api</artifactId>
        </dependency>
    </dependencies>

    <!-- 如果父工程cjs-store的parent不是cjs-dependencies-bom,則這裡需要import,否則不需要,因為可以直接透過繼承得到 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.example</groupId>
                <artifactId>cjs-dependencies-bom</artifactId>
                <version>1.0.0-SNAPSHOT</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

其實,這種依賴包管理可以學習一下dubbo

5.  專案啟動問題

如果你的springboot專案起不來,控制檯也不列印任何報錯資訊,就像這樣

那麼,你可以在SpringApplication.run()這一行打斷點

然後,就可以看到報錯了

6.  演示

Maven – Settings Reference (apache.org)

Maven – Guide to Mirror Settings (apache.org)

Maven – POM Reference (apache.org)

Maven – Best Practice - Using a Repository Manager (apache.org)

相關文章