ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

maven的聚合和继承详解(2021版)

2021-01-22 22:33:41  阅读:156  来源: 互联网

标签:依赖 version springframework maven POM 2021 模块 org 详解


前言:日常开发中,两处常见的项目开发场景:多模块项目或者Springboot项目,都会用到Maven的聚合和继承,本篇博客就针对maven这两个技术点进行总结整理,希望能对你有所帮助!

在进入正题之前,先看一下如下项目结构erms作为父模块或者聚合模块,下面有8个模块,每个模块都有自己单独的pom.xml文件。来思考以下两个问题:

  1. 如果要打包部署war包(简单点就是一次构建多个项目)的话,岂不是需要到每个不同的模块下执行mvn命令来完成打包操作?
  2. 如果不同模块需要依赖相同的jar包,难道需要在需要的模块下分别编写依赖吗?如果依赖或者依赖版本改动的话,岂不是需要改动多处?

一、聚合

聚合的出现主要是为了方便快速构建项目。比如我们在实际项目开发中会应用分层成多个maven项目,传统模式下我们需要按照一定的顺序去不同的maven项目下执行mvn命令,这种重复机械性的操作给开发带来了诸多不便。Maven聚合(或称为多模块)这一特性就时允许一次构建多个项目。

一般来说,为了方便快速定位内容,模块所处的目录名称应当与其artifactId一致;

通常将聚合模块放在项目目录的最顶层,其它模块作为聚合模块的子目录存在;聚合模块仅仅是帮助聚合其它模块构建的工具,它本身并无实质的内容

二、继承

2.1 概念在聚合部分中,我们知道一个项目可以是多模块项目,如果不同模块中有许多相同的配置,比如相同的groupId和version,相同的依赖和插件配置,即在不同的pom文件中出现重复的内容,重复往往意味着更多的劳动和潜在的问题。在面向对象编程中,我们可以通过类的继承机制一定程度上解决重复问题。在maven中同样可以通过pom的继承抽取出重复的配置来解决重复;

简单来说就是创建一个父pom文件并声明一些配置,供子类继承;Maven的继承机制只是为了消除配置的重复,子模块可以通过以下配置来实现继承

<parent>
        <artifactId>hzrj-aggregation</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

2.2 可继承内容:那么子pom可以从父pom继承哪些内容呢,如下所示,大家简单记录下常用即可:

  • groupId :项目组 ID ,项目坐标的核心元素;
  • version :项目版本,项目坐标的核心元素;
  • description :项目的描述信息;
  • organization :项目的组织信息;
  • inceptionYear :项目的创始年份;
  • url :项目的 url 地址
  • develoers :项目的开发者信息;
  • contributors :项目的贡献者信息;
  • distributionManagerment :项目的部署信息;
  • issueManagement :缺陷跟踪系统信息;
  • ciManagement :项目的持续继承信息;
  • scm :项目的版本控制信息;
  • mailingListserv :项目的邮件列表信息;
  • properties :自定义的 Maven 属性;
  • dependencies :项目的依赖配置;
  • dependencyManagement :醒目的依赖管理配置;
  • repositories :项目的仓库配置;
  • build :包括项目的源码目录配置、输出目录配置、插件配置、插件管理配置等;
  • reporting :包括项目的报告输出目录配置、报告插件配置等。

2.3 当我们利用继承将子模块中所依赖的所有内容都放到父POM中后又延伸出一个新的问题:这样会导致父POM中的依赖是所有子模块的并集(假设有30个),即包含所有子模块依赖,这就导致子模块在继承父POM后会继承父POM中所有依赖,但子模块可能只需要其中少数几个依赖(假设10个),但却依赖了大量自己不需要的依赖;对此有两种思路:

类似面向对象的编程中父POM只配置所有子模块依赖的交集,子模块独有的依赖由子模块单独配置。这种方式是可行的,但比如有A,B,C三个模块,最开始只有模块A依赖junit,到了后来模块B也依赖junit,那么这个时候就可能需要在模块B中引入junit依赖。相当于在模块A和B中都需要配置groupId、artifactId和version等,每次junit依赖改动(比如版本升级或者artifactId变动)都需要修改对应模块的依赖部分内容;

针对上述问题,比较好的一种思路是:父POM中统一配置所有依赖的完整声明,子模块在没有显示引入依赖时不会引入实际依赖,只有子模块在dependencies下通过dependency元素才会正式引入依赖;既保证子模块灵活使用依赖的同时,也约束了依赖的使用;对此Maven提供了dependencyManagement元素来提供上述功能,如下所示,我们在父POM进行如下配置,虽然dependencyManagement配置了几个依赖,但并不会引入任何依赖,只是起到了依赖的完整声明。

<properties>
	<junit-version>4.12</junit-version>
	<springframework-version>4.3.7.RELEASE</springframework-version>
	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	<mybatis-version>3.4.1</mybatis-version>
	<mybatis-spring-version>1.3.0</mybatis-spring-version>
	<hibernate-validator-version>5.4.1.Final</hibernate-validator-version>
</properties>
<dependencyManagement>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>${junit-version}</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>${mybatis-version}</version>
		</dependency>
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis-spring</artifactId>
			<version>${mybatis-spring-version}</version>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-validator</artifactId>
			<version>${hibernate-validator-version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${springframework-version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>${springframework-version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-redis</artifactId>
			<version>1.8.6.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context-support</artifactId>
			<version>${springframework-version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aop</artifactId>
			<version>${springframework-version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aspects</artifactId>
			<version>${springframework-version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>${springframework-version}</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
</dependencyManagement>

接下来我们只需要在子POM文件中做如下配置即可引入依赖,最终实际引入的依赖只有junit和mybatis,由于junit和mybatis的version和scope属性已在父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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>hzrj-aggregation</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>hzrj-submodule</artifactId>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
        </dependency>
    </dependencies>
</project>

扩展:大家都知道一个Springboot项目的POM文件,一般都采用Maven继承,即通过parent关键字继承自官方提供的spring-boot-starter-parent:

<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>2.2.1.RELEASE</version>
	<relativePath/> <!-- lookup parent from repository -->
</parent>

但比如当前项目已经有了父POM,但又想使用spring-boot提供的功能,由于Maven是单继承,那么对此可以使用dependencyManagement导入的用法来解决,以下配置的作用是:将spring-boot-dependencies POM中的dependencyManagement配置导入并合并到当前POM的dependencyManagement元素中,注意import这个依赖范围,这个依赖范围只在dependencyManagement元素下才有作用,且它所指向的依赖通常是一个打包类型为POM的模块;

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

三、聚合和继承的关系

聚合是为了方便快速构建项目,而继承是为了消除重复配置。实际项目中并不会严格地把聚合和继承分开,往往会发现一个POM既是聚合POM,又是继承POM。无论如何变化记住本质即可。

以上,完了!

 

 

标签:依赖,version,springframework,maven,POM,2021,模块,org,详解
来源: https://blog.csdn.net/yu102655/article/details/112915377

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有