maven
Maven 的主要作用主要有 3 个:
- 项目构建:提供标准的、跨平台的自动化项目构建方式。
- 依赖管理:方便快捷的管理项目依赖的资源(jar 包),避免资源间的版本冲突问题。
- 统一开发结构:提供标准的、统一的项目结构。
maven项目结构
Maven 的标准工程结构如下
|-- pom.xml(maven的核心配置文件)
|-- src
|-- main
|-- java(java源代码目录)
|-- resources(资源文件目录)
|-- test
|-- java(单元测试代码目录)
|-- target(输出目录,所有的输出物都存放在这个目录下)
|-- classes(编译后的class文件存放处)
POM结构
总体结构
每一个 Maven 工程都有一个 pom.xml 文件,位于根目录中,包含项目构建生命周期的详细信息。
通过 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>
<!-- The Basics -->
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>...</version>
<packaging>...</packaging>
<dependencies>...</dependencies>
<parent>...</parent>
<dependencyManagement>...</dependencyManagement>
<modules>...</modules>
<properties>...</properties>
<!-- Build Settings -->
<build>...</build>
<reporting>...</reporting>
<!-- More Project Information -->
<name>...</name>
<description>...</description>
<url>...</url>
<inceptionYear>...</inceptionYear>
<licenses>...</licenses>
<organization>...</organization>
<developers>...</developers>
<contributors>...</contributors>
<!-- Environment Settings -->
<issueManagement>...</issueManagement>
<ciManagement>...</ciManagement>
<mailingLists>...</mailingLists>
<scm>...</scm>
<prerequisites>...</prerequisites>
<repositories>...</repositories>
<pluginRepositories>...</pluginRepositories>
<distributionManagement>...</distributionManagement>
<profiles>...</profiles>
</project>
在下面说明部分常用配置的基本概念
项目基础信息
坐标三元组:groupId(组织标识)、artifactId(项目标识)、version构成项目唯一标识
- version:maven 在版本管理时候可以使用几个特殊的字符串 SNAPSHOT、LATEST、RELEASE
- SNAPSHOT - 这个版本一般用于开发过程中,表示不稳定的版本。
- LATEST - 指某个特定构件的最新发布,这个发布可能是一个发布版,也可能是一个 snapshot 版,具体看哪个时间最后。
- RELEASE :指最后一个发布版
packaging定义构建输出类型(jar/war/pom等)
packaging - 项目的类型,描述了项目打包后的输出,默认是 jar。常见的输出类型为:pom, jar, maven-plugin, ejb, war, ear, rar, par
name和description为项目描述信息
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.xxx.demo</groupId>
<artifactId>my-project</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>My Project</name>
<description>示例项目</description>
</project>
继承parent与依赖管理dependencies
parent实现POM继承,统一多项目配置
properties定义全局变量,提高可维护性
dependencyManagement集中管理依赖版本
<parent>
<groupId>com.xxx.parent</groupId>
<artifactId>base-pom</artifactId>
<version>2.0</version>
</parent>
<properties>
<java.version>17</java.version>
<spring.version>6.1.0</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>...</dependencies>
</dependencyManagement>
继承 parent
子 POM 可以使用 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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.xx.xx</groupId>
<artifactId>my-parent</artifactId>
<version>2.0</version>
// 在搜索本地和远程存储库之前,它不是必需的,但可以用作 maven 的指示符,以首先搜索给定该项目父级的路径
<relativePath>../my-parent</relativePath>
</parent>
<artifactId>my-project</artifactId>
</project>
依赖 dependencies
dependencie
项目中依赖的第三方库以及插件可统称为构件。每一个构件都可以使用 Maven 坐标唯一标识
,
坐标元素包括:
groupId(必须): 定义了当前 Maven 项目隶属的组织或公司
。artifactId(必须):定义了当前 Maven 项目的名称
,项目的唯一的标识符,对应项目根目录的名称。version(必须):定义了 Maven 项目当前所处版本
。- packaging(可选):定义了 Maven 项目的打包方式(比如 jar,war…),默认使用 jar。
- classifier(可选):常用于区分从同一 POM 构建的具有不同内容的构件,可以是任意的字符串,附加在版本号之后。
如下
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.1.1</version>
</dependency>
依赖配置 dependencies
常见配置信息如下
<project>
<dependencies>
<dependency>
<groupId></groupId>
<artifactId></artifactId>
<version></version>
<type>...</type>
<scope>...</scope>
<optional>...</optional>
<exclusions>
<exclusion>
<groupId>...</groupId>
<artifactId>...</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>
配置说明:
dependencies:一个 pom.xml 文件中只能存在一个
这样的标签,是用来管理依赖的总标签。dependency
:包含在 dependencies 标签中,可以有多个,每一个表示项目的一个依赖
。groupId,artifactId,version(必要):依赖的基本坐标
,对于任何一个依赖来说,基本坐标是最重要的,Maven 根据坐标才能找到需要的依赖。- type(可选):依赖的类型,对应于项目坐标定义的 packaging。大部分情况下,该元素不必声明,其默认值是 jar。
- scope(可选):依赖的范围,默认值是 compile。
- optional(可选):标记依赖是否可选
exclusions(可选):用来排除传递性依赖,例如 jar 包冲突
依赖范围 scope
classpath 用于指定 .class 文件存放的位置,类加载器会从该路径中加载所需的 .class 文件到内存中。
Maven 在编译、执行测试、实际运行有着三套不同的 classpath:
- 编译 classpath:编译主代码有效
- 测试 classpath:编译、运行测试代码有效
- 运行 classpath:项目运行时有效
Maven 的依赖范围如下:
compile:编译依赖范围(默认),使用此依赖范围对于编译、测试、运行三种都有效
,即在编译、测试和运行的时候都要使用该依赖 Jar 包。test:测试依赖范围,从字面意思就可以知道此依赖范围只能用于测试
,而在编译和运行项目时无法使用此类依赖,典型的是 JUnit,它只用于编译测试代码和运行测试代码的时候才需要。provided:此依赖范围,对于编译和测试有效,而对运行时无效
。比如 servlet-api.jar 在 Tomcat 中已经提供了,我们只需要的是编译期提供而已。runtime:运行时依赖范围,对于测试和运行有效,但是在编译主代码时无效
,典型的就是 JDBC 驱动实现。system:系统依赖范围,使用 system 范围的依赖时必须通过 systemPath 元素显示地指定依赖文件的路径,不依赖 Maven 仓库解析
,所以可能会造成建构的不可移植。
dependencyManagement
使用<dependencyManagement>统一版本管理,子模块只需声明groupId和artifactId
dependencyManagement 主要是为了统一管理依赖包的版本,确保所有子项目使用的版本一致,类似的还有plugins和pluginManagement
。
示例:父项目中可以利用 dependencyManagement 声明子项目中需要用到的依赖 jar 包,之后,当某个或者某几个子项目需要加载该依赖的时候,就可以在子项目中 dependencies 节点只配置 groupId 和 artifactId 就可以完成依赖的引用
属性列表 properties
这里面定义的属性可以在 pom.xml 文件中任意处使用。
<!-- 全局属性 -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>17</java.version>
<spring.version>6.1.0.RELEASE</spring.version>
</properties>
构建配置 build
插件配置与生命周期阶段绑定
编译参数、资源文件过滤等配置
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
<resources>...</resources>
</build>
resources
resources: 资源元素的列表,每个资源元素描述与此项目关联的文件和何处包含文件。
targetPath: 指定从构建中放置资源集的目录结构。目标路径默认为基本目录。将要包装在 jar 中的资源的通常指定的目标路径是 META-INF。
filtering: 值为 true 或 false。表示是否要为此资源启用过滤。请注意,该过滤器 * .properties 文件不必定义为进行过滤
includes: 一组文件匹配模式,指定目录中要包括的文件,使用*作为通配符
excludes: 与 includes 类似,指定目录中要排除的文件,使用*作为通配符。
注意:如果 include 和 exclude 发生冲突,maven 会以 exclude 作为有效项。
<resources>
<resource>
<targetPath>META-INF/plexus</targetPath>
<filtering>false</filtering>
<directory>${basedir}/src/main/plexus</directory>
<includes>
<include>configuration.xml</include>
</includes>
<excludes>
<exclude>**/*.properties</exclude>
</excludes>
</resource>
</resources>
testResources
testResources: testResources 与 resources 功能类似,区别仅在于:testResources 指定的资源仅用于 test 阶段,并且其默认资源目录为:${basedir}/src/test/resources
plugins
groupId, artifactId, version :和基本配置中的 groupId、artifactId、version 意义相同
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
多模块管理modules
声明子模块路径,用于聚合构建
父POM使用packaging=pom类型
<modules>
<module>core</module>
<module>api</module>
</modules>
环境配置
实现不同环境(开发/测试/生产)差异化配置
通过-P prod激活特定配置
profiles
<profiles>
<profile>
<id>prod</id>
<properties>
<env>production</env>
</properties>
</profile>
</profiles>
Maven 依赖 配置 常见问题
如果使用 Maven 构建产生的构件(例如 Jar 文件)被其他的项目引用,那么该构件就是其他项目的依赖
。
依赖冲突
避免依赖重复
对于 Maven 而言,同一个 groupId 同一个 artifactId 下,只能使用一个 version
若相同类型但版本不同的依赖存在于同一个 pom 文件,只会引入后一个声明的依赖若相同类型但版本不同的依赖存在于同一个 pom 文件,只会引入后一个声明的依赖
项目的两个依赖同时引入了某个依赖
。
如下:为了避免依赖重复,Maven 只会选择其中的一个进行解析
依赖链路一:A -> B -> C -> X(1.0)
依赖链路二:A -> D -> X(2.0)
如何解决冲突
首先,找到 Maven 加载的 Jar 包版本,使用 mvn dependency:tree 查看依赖树,根据依赖原则来调整依赖在 POM 文件的声明顺序
发现了冲突的包之后,剩下的就是选择一个合适版本的包留下,
- 如果是传递依赖的包正确,那么把显示依赖的包exclude掉。
- 如果是某一个传递依赖的包有问题,那么我们需要手动把这个传递依赖execlude掉
Maven 依赖调解
路径最短优先
如下:依赖链路二的路径最短,因此,X(2.0)会被解析使用。
依赖链路一:A -> B -> C -> X(1.0) // dist = 3
依赖链路二:A -> D -> X(2.0) // dist = 2
如果像下面这样,便需要遵从 顺序优先原则
依赖链路一:A -> B -> X(1.0) // dist = 2
依赖链路二:A -> D -> X(2.0) // dist = 2
声明顺序优先
在依赖路径长度相等的前提下,在 pom.xml 中依赖声明的顺序决定了谁会被解析使用,顺序最前的那个依赖优胜
依赖链路一:A -> B -> X(1.0) // dist = 2
依赖链路二:A -> D -> X(2.0) // dist = 2
如上例,声明规则如下:B 的依赖声明在 D 之前,那么 X (1.0)就会被解析使用
<!-- A pom.xml -->
<dependencies>
...
dependency B
...
dependency D
</dependencies>
排除依赖exclusion
单纯依赖 Maven 来进行依赖调解,在很多情况下是不适用的,需要我们手动排除依赖
如下:根据路径最短优先原则,X(1.0) 会被解析使用,但是会有下面的问题
- 如果 C 依赖用到了 1.5 版本的 X 中才有的一个类,运行项目就会报NoClassDefFoundError错误。
- 如果 C 依赖用到了 1.5 版本的 X 中才有的一个方法,运行项目就会报NoSuchMethodError错误
依赖链路一:A -> B -> C -> X(1.5) // dist = 3
依赖链路二:A -> D -> X(1.0) // dist = 2
所以,便需要使用exclusion把X(1.0)排除,如下
<dependency>
......
<exclusions>
<exclusion>
<artifactId>x</artifactId>
<groupId>org.apache.x</groupId>
</exclusion>
</exclusions>
</dependency>
在解决依赖冲突的时候,都会优先保留版本较高的。这是因为大部分 jar 在升级的时候都会做到向下兼容
。
如下:保留了 1.5 版本的 X,但是这个版本的 X 删除了 1.0 版本中的某些类。这个时候,我们可以考虑升级 D 的版本到一个 X 兼容的版本。
依赖链路一:A -> B -> C -> X(1.5) // dist = 3
依赖链路二:A -> D -> X(1.0) // dist = 2
引入本地 jar
通过设置 dependency 的 scope 为 system 来引入本地 jar
将私有 jar 放置在 resouces/lib 下,然后安下面的方式添加依赖:
groupId 和 artifactId 可以按照 jar 包中的 package 设置,只要和其他 jar 不冲突即可
<dependency>
<groupId>xxx</groupId>
<artifactId>xxx</artifactId>
<version>1.0.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/lib/xxx-6.0.0.jar</systemPath>
</dependency>
指定 JDK 版本
使用properties 方式
<project>
...
<properties>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
...
</project>
不将 dependency 同时打包
指定 maven dependency 的 scope 为 provided
意味着:依赖关系将在运行时由其容器或 JDK 提供
Maven 仓库
基本概念
任何一个依赖、插件或者项目构建的输出,都可以称为 构件
坐标和依赖是构件在 Maven 世界中的逻辑表示方式,构件的物理表示方式是文件,Maven 通过仓库来统一管理这些文件
任何一个构件都有一组坐标唯一标识。
有了仓库之后,无需手动引入构件,我们直接给定构件的坐标即可在 Maven 仓库中找到该构件。
分类
Maven 仓库分为:
本地仓库:运行 Maven 的计算机上的一个目录
,它缓存远程下载的构件并包含尚未发布的临时构件。settings.xml 文件中可以看到 Maven 的本地仓库路径配置,默认本地仓库路径是在 ${user.home}/.m2/repository
。- 远程仓库:官方或者其他组织维护的 Maven 仓库,可以分为:
中央仓库:这个仓库是由 Maven 社区来维护的,里面存放了绝大多数开源软件的包,并且是作为 Maven 的默认配置,不需要开发者额外配置
。私服
:私服是一种特殊的远程 Maven 仓库,它是架设在局域网内的仓库服务,私服一般被配置为互联网远程仓库的镜像,供局域网内的 Maven 用户使用
。其他的公共仓库:有一些公共仓库是为了加速访问
(比如阿里云 Maven 镜像仓库)或者部分构件不存在于中央仓库中
。
Maven 依赖包寻找顺序
Maven 依赖包寻找顺序
先去本地仓库找寻
,有的话,直接使用。- 本地仓库没有找到的话,
会去远程仓库找寻,下载包到本地仓库
。 远程仓库没有找到的话,会报错
Maven 生命周期
基本概念
Maven 定义了 3 个生命周期META-INF/plexus/components.xml
- default 生命周期
- clean生命周期
- site生命周期
这些生命周期是相互独立的,每个生命周期包含多个阶段(phase)
前面的阶段依赖于前面的阶段。当执行某个阶段的时候,会先执行它前面的阶段
Maven 生命周期的命令格式
mvn 阶段 [阶段2] ...[阶段n]
default 生命周期
是在没有任何关联插件的情况下定义的,是 Maven 的主要生命周期,用于构建应用程序,共包含 23 个阶段。
<phases>
<!-- 验证项目是否正确,并且所有必要的信息可用于完成构建过程 -->
<phase>validate</phase>
<!-- 建立初始化状态,例如设置属性 -->
<phase>initialize</phase>
<!-- 生成要包含在编译阶段的源代码 -->
<phase>generate-sources</phase>
<!-- 处理源代码 -->
<phase>process-sources</phase>
<!-- 生成要包含在包中的资源 -->
<phase>generate-resources</phase>
<!-- 将资源复制并处理到目标目录中,为打包阶段做好准备。 -->
<phase>process-resources</phase>
<!-- 编译项目的源代码 -->
<phase>compile</phase>
<!-- 对编译生成的文件进行后处理,例如对 Java 类进行字节码增强/优化 -->
<phase>process-classes</phase>
<!-- 生成要包含在编译阶段的任何测试源代码 -->
<phase>generate-test-sources</phase>
<!-- 处理测试源代码 -->
<phase>process-test-sources</phase>
<!-- 生成要包含在编译阶段的测试源代码 -->
<phase>generate-test-resources</phase>
<!-- 处理从测试代码文件编译生成的文件 -->
<phase>process-test-resources</phase>
<!-- 编译测试源代码 -->
<phase>test-compile</phase>
<!-- 处理从测试代码文件编译生成的文件 -->
<phase>process-test-classes</phase>
<!-- 使用合适的单元测试框架(Junit 就是其中之一)运行测试 -->
<phase>test</phase>
<!-- 在实际打包之前,执行任何的必要的操作为打包做准备 -->
<phase>prepare-package</phase>
<!-- 获取已编译的代码并将其打包成可分发的格式,例如 JAR、WAR 或 EAR 文件 -->
<phase>package</phase>
<!-- 在执行集成测试之前执行所需的操作。 例如,设置所需的环境 -->
<phase>pre-integration-test</phase>
<!-- 处理并在必要时部署软件包到集成测试可以运行的环境 -->
<phase>integration-test</phase>
<!-- 执行集成测试后执行所需的操作。 例如,清理环境 -->
<phase>post-integration-test</phase>
<!-- 运行任何检查以验证打的包是否有效并符合质量标准。 -->
<phase>verify</phase>
<!-- 将包安装到本地仓库中,可以作为本地其他项目的依赖 -->
<phase>install</phase>
<!-- 将最终的项目包复制到远程仓库中与其他开发者和项目共享 -->
<phase>deploy</phase>
</phases>
clean 生命周期
clean 生命周期的目的是清理项目,共包含 3 个阶段
:
- pre-clean
- clean
- post-clean
<phases>
<!-- 执行一些需要在clean之前完成的工作 -->
<phase>pre-clean</phase>
<!-- 移除所有上一次构建生成的文件 -->
<phase>clean</phase>
<!-- 执行一些需要在clean之后立刻完成的工作 -->
<phase>post-clean</phase>
</phases>
<default-phases>
<clean>
org.apache.maven.plugins:maven-clean-plugin:2.5:clean
</clean>
</default-phases>
当我们执行 mvn clean 的时候,会执行 clean 生命周期中的 pre-clean 和 clean 阶段
site 生命周期
site 生命周期的目的是建立和发布项目站点,共包含 4 个阶段:
- pre-site
- site
- post-site
- site-deploy
<phases>
<!-- 执行一些需要在生成站点文档之前完成的工作 -->
<phase>pre-site</phase>
<!-- 生成项目的站点文档作 -->
<phase>site</phase>
<!-- 执行一些需要在生成站点文档之后完成的工作,并且为部署做准备 -->
<phase>post-site</phase>
<!-- 将生成的站点文档部署到特定的服务器上 -->
<phase>site-deploy</phase>
</phases>
<default-phases>
<site>
org.apache.maven.plugins:maven-site-plugin:3.3:site
</site>
<site-deploy>
org.apache.maven.plugins:maven-site-plugin:3.3:deploy
</site-deploy>
</default-phases>
Maven 能够基于 pom.xml 所包含的信息,自动生成一个友好的站点,方便团队交流和发布项目信息。
常用的 maven命令
使用mvn这个命令时,后面的参数是phase,Maven自动根据生命周期运行到指定的phase
如下:
-
运行mvn package,Maven就会执行default生命周期,它会从开始一直运行到package这个phase为止
-
运行mvn compile,Maven也会执行default生命周期,但这次它只会运行到compile
-
更复杂的例子是指定多个phase,例如,运行mvn clean package
经常使用的命令有:
- mvn clean:清理所有生成的class和jar;
- mvn clean compile:先清理,再执行到compile;
- mvn clean test:先清理,再执行到test,因为执行test前必须执行compile,所以这里不必指定compile;
- mvn clean package:先清理,再执行到package。
Maven 插件
Maven 本质上是一个插件执行框架,所有的执行过程,都是由一个一个插件独立完成的
。
Maven 插件为一组任务的集合,用户可以通过命令行直接运行指定插件的任务,也可以将插件任务挂载到构建生命周期,随着生命周期运行
Maven 插件被分为下面两种类型:
- Build plugins:在构建时执行。
- Reporting plugins:在网站生成过程中执行。
使用Maven,实际上就是配置好需要使用的插件,然后通过phase调用它们。
Maven已经内置了一些常用的标准插件:
插件名称 | 对应执行的phase |
---|---|
clean | clean |
compiler | compile |
surefire | test |
jar | package |
Maven 多模块管理
将一个项目分为多个模块,每个模块只负责单一的功能实现
多模块管理下,会有一个父模块,其他的都是子模块。
每个模块当作一个独立的Maven项目,它们有各自独立的pom.xml
父模块通常只有一个 pom.xml
,没有其他内容。父模块的 pom.xml 一般只定义了各个依赖的版本号、包含哪些子模块以及插件有哪些
┌ ─ ─ ─ ─ ─ ─ ┐
┌─────────┐
│ │Module A │ │
└─────────┘
┌──────────────┐ split │ ┌─────────┐ │
│Single Project│───────▶ │Module B │
└──────────────┘ │ └─────────┘ │
┌─────────┐
│ │Module C │ │
└─────────┘
└ ─ ─ ─ ─ ─ ─ ┘
Maven最佳实践
Maven 标准目录结构
aven 项目的标准目录结构如下:
- src/main/java:源代码目录
- src/main/resources:资源文件目录
- src/test/java:测试代码目录
- src/test/resources:测试资源文件目录
src/
main/
java/
resources/
test/
java/
resources/
pom.xml
指定 Maven 编译器插件
默认情况下,Maven 使用 Java5 编译我们的项目。
要使用不同的 JDK 版本,需要在 pom.xml 文件中配置 Maven 编译器插件。
例如,如果你想要使用 Java8 来编译你的项目,你可以在<build>标签下
添加以下的代码片段:
如果你想要使用其他版本的 JDK,你只需要修改<source>和<target>标签的值
即可
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
有效管理依赖关系
在顶层 pom 文件中,通过标签 dependencyManagement 定义公共的依赖关系,这有助于避免冲突并确保所有模块使用相同版本的依赖项
例如,假设我们有一个父模块和两个子模块 A 和 B,我们想要在所有模块中使用 JUnit 5.7.2 作为测试框架
。我们可以在父模块的pom.xml文件中使用<dependencyManagement>标签来定义 JUnit 的版本
父pom
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.7.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
在子模块 A 和 B 的 pom.xml 文件中,我们只需要引用 JUnit 的 groupId 和 artifactId 即可:
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
</dependency>
</dependencies>