maven的pom.xml文件中parent,dependencyManagement、dependencies标签是我们经常要用到的,其中parent的作用是引用父工程,dependencyManagement只能位于父工程中,相当于一个对所依赖jar包进行版本管理的管理器,只是声明依赖,并不实现引入,dependencies是对所需要的的jar包进行引入。
1、应用场景
在多模块(module)的项目中,有很多模块中的pom中存在相同的引用,如果此时声明一个父pom文件,将公用的依赖提取到父pom文件中(即使用 <parent>
标签),将大大减少其他pom文件中的依赖的配置。parent标签能够管理多个项目之间公共的依赖,和 java 中的继承相当,作用就是复用。
例如一个项目中有2个module,分别为A模块、B模块,它们都需要依赖一些共同的jar包(如domain.jar,当然jar包可能有多个共有的),如果我们分别在A、B模块各自的pom文件中引入domain.jar的依赖,那么当domain.jar的版本发生变化时,这2个模块的pom文件都要改,项目中依赖越多修改越多。
该场景下我们就需要用到parent标签:
- 创建一个新的module,名为parent(当然也可以叫其他名字),存放父pom,parent项目的打包类型为pom,且parent项目中没有任何代码,只是管理多个项目之间公共的依赖。
- 父pom中,可以使用parent标签(定义大部分module都使用的组件,如spirng boot)。
- 父pom中,可以定义dependencyManagement标签,管理其他模块共同依赖的jar包版本(定义公共依赖),当这些公共依赖的版本号需要修改时,只需要修改parent的dependencyManagement中的版本就可以了。
- 父pom中,可以定义dependencies标签,该标签下定义的jar为所有模块共同依赖的jar包。
- 在其他两个module中使用parent标签,其坐标就是父pom中声明的坐标。这2个module作为parent模块的子模块。
- 在子模块中dependencies标签中,可以直接使用parent模块中dependencyManagement标签定义的jar,而不需要指定版本号(如果子模块指定了公共依赖jar包的版本号,则以子模块的版本号为主)。
2、使用方式
2.1 parent标签
- 创建一个新的module,名为parent,存放父pom
<groupId>com.demo</groupId>
<artifactId>parent</artifactId>
<version>0.0.1</version>
<packaging>pom</packaging>
<!-- 这里的parent标签页视情况而定,非必须的,如果所有子项目都依赖springboot,就这样定义 -->
<parent>
<!--这是Spring Boot的父级依赖,这样当前的项目就是Spring Boot项目了。
spring-boot-starter-parent 是一个特殊的starter,它用来提供相关的Maven默认依赖。
使用它之后,常用的包依赖可以省去version标签。-->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
<!--查找顺序:relativePath元素中的地址–本地仓库–远程仓库,
设定一个空值将始终从仓库中获取,不从本地路径获取-->
<relativePath/>
</parent>
- 在其他两个module中使用parent标签
<parent>
<groupId>com.demo</groupId>
<artifactId>parent</artifactId>
<version>0.0.1</version>
</parent>
通过这一步,所有的子模块都可以使用父模块定义的springboot,如果需要修改springboot的版本,只需要修改父pom.xml中parent的version版本号。另外在每个模块中都可以定义properties属性,可以自定义一个或多个Maven属性,然后在POM的其他地方使用${属性名}的方式引用该属性,这种做法的最大意义在于消除重复和统一管理。在父模块中定义的属性可以直接在子模块中使用。
2.2 dependencyManagement标签
在Maven中dependencyManagement的作用其实相当于一个对所依赖jar包进行版本管理的管理器,只是声明依赖,并不实现引入,只有在某个模块中显示引入某个依赖的时候才会真正的引入jar包。
- dependencyManagement里只是声明依赖,并不实现引入,因此子项目需要显式的声明需要用的依赖。如果不在子项目中声明依赖,是不会从父项目中继承下来的;只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且version和scope都读取自父pom;另外如果子项目中指定了版本号,那么会使用子项目中指定的jar版本。
- import只在dependencyManagement元素下才有效果,作用是将目标POM中的dependencyManagement配置导入并合并到当前POM的dependencyManagement元素中。
在父模块parent中定义的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.demo</groupId>
<artifactId>parent</artifactId>
<version>0.0.1</version>
<packaging>pom</packaging>
<name>parent</name>
<description>parent demo</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<druid.version>1.2.8</druid.version>
<fastjson.version>1.2.76</fastjson.version>
<commons.collections.version>3.2.2</commons.collections.version>
</properties>
<!-- 依赖声明 -->
<dependencyManagement>
<dependencies>
<!-- SpringBoot的依赖配置,和上例中parent标签的作用相同,这样做可以让子模块定义自己需要的parent-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.13.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- 阿里数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<!-- collections工具类 -->
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>${commons.collections.version}</version>
</dependency>
<!-- 阿里JSON解析器 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<modules>
<module>a-module</module>
<module>b-module</module>
</modules>
<dependencies>
</dependencies>
<pluginRepositories>
<pluginRepository>
<id>public</id>
<name>aliyun nexus</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>
2.3 dependencies标签
在子模块中可以使用dependencies标签引入需要使用的jar包,如果是公共依赖(即在父模块dependencyManagement中已经定义的jar),则不需要指定版本号。如果父模块定义了dependencies依赖,子模块会自动引入这些依赖,但不会自动引入dependencyManagement的依赖。
子模块的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">
<parent>
<artifactId>parent</artifactId>
<groupId>com.demo</groupId>
<version>0.0.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<artifactId>a-module</artifactId>
<description>
A模块
</description>
<dependencies>
<!-- 阿里数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<!-- collections工具类 -->
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
</dependency>
<!-- 阿里JSON解析器 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
</dependencies>
</project>
在dependencies标签中,根据需要引用需要的依赖,如果是父模块定义的公共依赖,则无须声明版本号。在子模块pom.xml文件中,jar的版本判断的两种途径:
- 如果dependencies里的dependency自己没有声明version元素,那么maven就会到dependencyManagement里面去找有没有对该artifactId和groupId进行过版本声明,如果有,就继承它,如果没有就会报错,告诉你必须为dependency声明一个version。
- 如果dependencies中的dependency声明了version,那么无论dependencyManagement中有无对该jar的version声明,都以dependency里的version为准。
2.4 dependencyManagement与dependencies区别:
- dependencyManagement里只是声明依赖,并不自动实现引入,因此子项目需要显示的声明需要用的依赖。
- dependencies相对于dependencyManagement,所有声明在dependencies里的依赖都会自动引入,并默认被所有的子项目继承。
- 子项目需要显示的声明需要用的依赖。如果不在子项目中声明依赖,是不会从父项目的dependencyManagement中继承下来的。
- 只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且version和scope都读取自父pom,如果子项目中指定了版本号,那么会使用子项目中指定的jar版本。
评论区