Maven依赖管理
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)