Maven 继承、聚合、属性


文章目录

  • 一、继承
    • 1.1. 概念
    • 1.2. 语法
    • 1.3. 示例
    • 1.4. 其他常见使用
  • 二、聚合
    • 2.1. 概念
    • 2.2. 示例
  • 三、属性
    • 3.1. Java 系统属性
    • 3.2.系统环境变量属性
    • 3.3.Maven 内置属性

一、继承

1.1. 概念


当项目较大,为了便于开发和管理,经常需要将工程划分成多个 Maven 工程(这些 Maven 工程此时被称为模块),这时模块间很可能会相互依赖,而每个模块的依赖信息都是模块单独管理,所以很可能导致依赖冲突,如下图:

模块间依赖冲突

很明显上图中,Lombok 模块发生了依赖冲突,虽然这种情况 Maven 仲裁机制会自动帮我们判定留下的版本是 Service 模块中的 Lombok 1.10.0,但如果 Dao 模块引用 Lombok 1.18.8 的目的就是为了使用 1.18.8 的新特性,这个时候就会有问题,因为最后留下来的版本 1.10.0 并不具备新特性

为了避免上述问题的发生,所以不建议在各个模块中单独管理依赖的版本信息,建议用一个专门的工程来统一管理依赖的版本,通常的情况下,所谓父工程,就是这个专门做依赖版本信息管理的工程

不只是多模块的场景适合父工程,建议每个公司都要有自己的一个公司级别的父工程,在工程中将多年总结下来的依赖间的版本搭配定义下来,之后有新项目启动时,都来继承这个父工程,减少版本兼容性的试验,


1.2. 语法


使用父工程来管理依赖版本,一共就两步:

  1. 父工程中指定 <packaging>pom</packaging>,并在 <dependencyManagement> 节点下声明各个依赖的版本信息
  2. 子模块中通过 <parent> 声明父工程的 GAV,之后依赖引用时不再需要 <version> 信息

1.3. 示例


(1)先定义一个父工程,其 pom.xml 如下:

<?xml version="1.0" encoding="UTF-8" standalone="no"?><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.ares5k</groupId><artifactId>ares5k-parent</artifactId><version>1.0-SNAPSHOT</version><!--  修改打包方式 --><packaging>pom</packaging><!-- 管理依赖的版本 --><dependencyManagement><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.8</version></dependency></dependencies></dependencyManagement>
</project>

<dependencyManagement> 节点下声明的依赖信息,并不会真正的将依赖引用进来,这里只是声明依赖版本而已


(2)再定义一个子模块,其 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><!-- 工程坐标 --><artifactId>ares5k-module</artifactId><!-- 指定父工程坐标--><parent><groupId>com.ares5k</groupId><artifactId>ares5k-parent</artifactId><version>1.0-SNAPSHOT</version><relativePath>../ares5k-parent/pom.xml</relativePath></parent><!-- 引入 lombok 依赖,不需要指定 version 信息 --><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies>
</project>

详细说明:

  • 当子模块的 <groupId><version> 与父工程相同时,在子模块中就可以将子模块的 <groupId><version> 省略

  • <relativePath> 用相对路径指定父工程 pom.xml 文件的位置,如果父工程已经安装在本地或远程仓库中,那么 <relativePath> 可以省略,<relativePath> 声明时,其寻找父工程的路径为 relativePath -> 本地仓库 -> 远程仓库

  • 子模块 <dependencies> 中的声明才是真正的把依赖引入进来,子模块如果不主动引入依赖,那么父工程 <dependencyManagement> 节点下声明的依赖就不会被真正的引入

1.4. 其他常见使用


在父工程中,除了管理依赖的版本,也经常用来管理生命周期插件、自定义属性、部署仓库、远程仓库等

自定义属性

自定义属性的使用方式:在 <properties> 下自定义节点,节点内的数据就属性值,定义后不管是父工程还是子模块,直接通过 ${自定义节点名} 就可以直接访问自定义属性

<!-- 声明自定义属性 -->
<properties><ares5k-lombok-version>1.18.8</ares5k-lombok-version><ares5k-jar-plugin>3.0.2</ares5k-jar-plugin>
</properties>
<!-- 使用自定义属性 -->
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>${ares5k-lombok-version}</version>
</dependency>

部署仓库 <distributionManagement> 和 远程仓库 <repositories> 在父工程声明后,子模块会直接继承该配置,不需要再声明。生命周期插件管理 <pluginManagement>,网上很多人说它和 <dependencyManagement> 一样,在父工程中声明后,如果子模块不主动引入,那么子模块就不会应用父工程 <dependencyManagement> 中配置的插件,这个说法,我测试是不正确的,最起码在 Maven 3.6.3 版本中不是这样的,只要在父工程 <dependencyManagement> 中声明了插件,不管子模块是否主动引入,在执行生命周期插件时,都会应用父工程中配置的插件


二、聚合


2.1. 概念

当有很多 Maven 工程都需要执行生命周期命令时,如果一个一个执行很浪费时间,所以可以通过创建一个聚合工程,将所有的 Maven 工程聚合到一起,然后统一执行命令

聚合

2.2. 示例

聚合工程就是一个普通的 Maven 工程,只不过需要设置 <packaging>pom</packaging>,然后在 <modules> 节点中将子模块目录的相对路径添加进来即可,<module> 中不是子模块的 <artifactId> 而是其与聚合工程的相对路径

<packaging>pom</packaging>
<modules><module>../ares5k-module-test</module><module>ares5k-module-inner</module>
</modules>

<modules> 添加好后就可以在聚合工程的 pom.xml 路径下运行生命周期命令,来统一构建

统一构建

到这里可能会发现聚合工程和继承用的父工程颇有相似的地方:

  1. 都需要创建一个单独的工程
  2. 都需要设置 <packaging>pom</packaging>

所以当既需要父工程又需要聚合工程的时候,为了避免冗余创建,基本都是只创建一个工程就可以,然后在该工程的 pom.xml 中将 <modules><dependencyManagement> 等节点都添加进去。这种做法尤其适合一个项目分为多个模块的场景,但是公司级的父工程还是比较适合单独创建

下图为我个人比较喜欢的 Maven 结构:
喜欢的Maven结构


三、属性


我们除了可以在 pom.xml 中使用自定义属性,也可以使用已有属性,已有属性大概分为:Java 系统属性、系统环境变量属性、Maven 内置属性

3.1. Java 系统属性

Java 系统属性包括:Java 默认的系统属性、运行 Java 程序时传入的虚拟机参数、Java 程序中自定义的系统属性,其使用语法很简单,就是 ${Java系统属性名}

打印 Java 系统属性列表

如果不知道 Java 系统属性都有什么,可以通过下面 Java 代码打印一下:

package com.ares5k;import java.util.Properties;
import java.util.Set;public class App {public static void main(String[] args) {Properties properties = System.getProperties();Set<Object> propNameSet = properties.keySet();for (Object propName : propNameSet) {String propValue = properties.getProperty((String) propName);System.out.println(propName + " = " + propValue);}}
}

运行上面代码后,会有类似如下结构的输出,= 左边的就是 Java 系统属性名,右边的是 Java 系统属性值,假如在 pom.xml 中使用 ${java.runtime.name},在 pom 文件运行时,就会将内容替换成 Java(TM) SE Runtime Environment

java.runtime.name = Java(TM) SE Runtime Environment
sun.boot.library.path = D:\java8\jre\bin
java.vm.version = 25.251-b08
java.vm.vendor = Oracle Corporation
java.vendor.url = http://java.oracle.com/
path.separator = ;
java.vm.name = Java HotSpot(TM) 64-Bit Server VM
file.encoding.pkg = sun.io
user.country = CN

3.2.系统环境变量属性

系统环境变量就是我们在操作系统中设置的环境变量,以 Windows 为例,下图就是系统变量,在 pom.xml 中通过语法 ${env.全大写系统变量名} 的方式就可以使用系统环境变量值,以下图中系统变量 ComSpec 为例,应该写成 ${env.COMSPEC}

Win系统变量


3.3.Maven 内置属性

除了能获取 Java 系统变量、操作系统环境变量,Maven 还提供了内置的属性

(1)访问 Pom 文件的节点

通过 ${project.标签名}${project.父标签.子标签} 可以访问 pom.xml 中的节点,不只可以访问当前工程 pom.xml 中的节点,超级 Pom 中的节点也可以访问

测试后,发现并不是所有的节点都能访问,列举一些我实验可用的:

属性说明
${project.basedir}项目在磁盘的全路径
${project.packaging}项目的打包方式
${project.groupId}项目的 groupId
${project.artifactId}项目的 artifactId
${project.version}项目的 version
${project.parent.groupId}父工程的 groupId
${project.parent.artifactId}父工程的 artifactId
${project.parent.version}父工程的 version
${project.parent.relativePath}到父工程目录的相对路径
${project.build.finalName}Maven 执行 package 阶段后的包名
${project.build.directory}构建后的输出目录
${project.build.sourceDirectory}源程序的目录
${project.build.outputDirectory}源程序编译后的输出目录
${project.build.testSourceDirectory}测试源程序的目录
${project.build.testOutputDirectory}测试源程序编译后的输出目录
${project.distributionManagement.repository.url}远程部署仓库中发版库的 URL
${project.distributionManagement.snapshotRepository.url}远程部署仓库中快照库的 URL

(2)访问Settings 文件的节点

通过 ${settings.标签名}${settings.父标签.子标签} 可以访问 Maven 安装目录/conf/settings.xml 中的节点,跟访问 Pom 文件一样,并不是所有节点都能成功访问,但是感觉 settings.xml 文件中没啥好总结的,就这样吧,就不列出了

(3)时间戳

可以通过 ${maven.build.timestamp} 获取当前时间,一般常用在打包后设置包名

如果对时间格式不满意,可以添加如下属性
<maven.build.timestamp.format>自定义时间格式</maven.build.timestamp.format> 来修改时间格式:

<!-- 自定义时间格式 -->
<properties><maven.build.timestamp.format>yyyy-MM-dd</maven.build.timestamp.format>
</properties>
<!-- 自定义包名 -->
<build><finalName>${project.artifactId}-${project.version}-${maven.build.timestamp}</finalName>
</build>

修改后通过 ${maven.build.timestamp} 就可以获取目标格式的自定义时间了,但是有一点要注意的是,通过这种方式获取的时间的时区是 UTC,并且无法修改时区,如果想修改时区,我们就不能用 ${maven.build.timestamp} 这种方式来获取时间,而是需要引入一个生命周期插件,代码如下:

<build><plugins><!-- 引入插件 --><plugin><groupId>org.codehaus.mojo</groupId><artifactId>build-helper-maven-plugin</artifactId><version>3.3.0</version><executions><execution><goals><goal>timestamp-property</goal></goals><configuration><!-- 自定义名称,后面输出日期时使用 --><name>build.time</name><!-- 设置日期格式 --><pattern>yyyyMMddHHmmss</pattern><!-- 设置时区 --><timeZone>GMT+8</timeZone></configuration></execution></executions></plugin></plugins><!-- 设置打包名:artifactId + version + 上面设置的时间自定义名称 --><finalName>${project.artifactId}-${project.version}-${build.time}</finalName>
</build>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/27772.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

奇迹MU架设教程:SQL Server 2008数据库的安装教程

不管是搭建什么游戏&#xff0c;都是有数据库的&#xff0c;奇迹MU用的是SQL 数据库&#xff0c;根据服务器系统选择SQL server版本&#xff0c;我比较喜欢用Windows server 2008R2系统&#xff0c;所以我安装的是SQL server 2008。作为架设奇迹很重要的数据库程序&#xff0c;…

Day13 02-Linux常用命令汇总

文章目录 第三章 Linux的常用命令【重要】3.1 命令格式的说明3.2 帮助命令3.2.1 man3.2.2 help 3.3 文件处理命令3.3.1 cd3.3.2 ls3.3.3 pwd3.3.4 mkdir3.3.5 touch3.3.6 echo3.3.7 cp3.3.8 mv3.3.9 rm3.3.10 vi编辑器3.3.11 ln 3.4 查看命令3.4.1 cat3.4.2 more3.4.3 head3.4.…

【Linux】进程概念

【Linux】进程概念 文章目录 【Linux】进程概念1、冯诺依曼体系结构2、操作系统2.1 概念2.2 设计OS的目的2.3 定位2.4 管理2.5 系统调用和库函数概念 3、进程3.1 基本概念3.2 描述进程—PCB3.3 组织进程3.4 查看进程3.5 获取进程标示符3.6 创建进程-fork初识3.7 进程状态3.7.1 …

ADC 的初识

ADC介绍 Q: ADC是什么&#xff1f; A: 全称&#xff1a;Analog-to-Digital Converter&#xff0c;指模拟/数字转换器 ADC的性能指标 量程&#xff1a;能测量的电压范围分辨率&#xff1a;ADC能辨别的最小模拟量&#xff0c;通常以输出二进制数的位数表示&#xff0c;比如&am…

分类预测 | MATLAB实现基于Attention-GRU的数据多特征分类预测(门控循环单元融合注意力机制分类预测,含混淆矩阵图、分类图)

分类预测 | MATLAB实现基于Attention-GRU的数据多特征分类预测(门控循环单元融合注意力机制分类预测&#xff0c;含混淆矩阵图、分类图) 目录 分类预测 | MATLAB实现基于Attention-GRU的数据多特征分类预测(门控循环单元融合注意力机制分类预测&#xff0c;含混淆矩阵图、分类图…

Flutter:网络图像缓存插件——cached_network_image

前言 为什么要使用这个插件&#xff0c;有什么用呢&#xff1f;毕竟官方提供了Image.network来进行网络图片加载 Image.network和CachedNetworkImage都可以用于在Flutter中加载网络图片&#xff0c;但它们之间有一些区别。 Image.network是Flutter核心库提供的一个构造函数&…

2020年国赛高教杯数学建模D题接触式轮廓仪的自动标注解题全过程文档及程序

2020年国赛高教杯数学建模 D题 接触式轮廓仪的自动标注 原题再现 轮廓仪是一种两坐标测量仪器&#xff08;见图1&#xff09;&#xff0c;它由工作平台、夹具、被测工件、探针、传感器和伺服驱动等部件组成&#xff08;见图2&#xff09;。   接触式轮廓仪的工作原理是&am…

阿里云推出“ModelScopeGPT”大模型调用工具,再添新贵

阿里云近日对外宣布将要推出其首款大模型调用工具——“魔搭GPT&#xff08;ModelScopeGPT&#xff09;”&#xff0c;从而为使用者们提供更为优质的人工智能应用支持。而作为阿里云人工智能产品家族中的新成员&#xff0c;这一创新工具也将进一步扩展阿里云在人工智能领域的影…

Stable Diffusion - ChatGPT4 与 Stable Diffusion 结合提供无限创意构图

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/131782672 ChatGPT 和 StableDiffusion 结合使用的优势&#xff1a; 高效率&#xff1a;ChatGPT 可以在很短的时间内完成复杂的语言任务&#xf…

05 Docker 安装常用软件 (mongoDB)

目录 1. mongoDB简介 1.1 mongodb的优势 2. mongodb的安装 2.1 创建数据文件夹 2.2 备份日志 2.3 配置文件夹 2.4 创建两个文件 ---> 2.4.1 配置如下: 2.5 拉取mongodb 2.6 运行容器 2.7 进入mongodb容器 ---> 2.7.0 高版本(6.0)以上是这样的 , 旧版的没研究 …

再度合作|极智嘉(Geek+) P系列拣选机器人进驻CEVA欧洲物流中心

近日&#xff0c;3PL巨头CEVA Logistics首度在社交媒体展示其与极智嘉(Geek)合作打造的全新欧洲物流中心&#xff0c;并在推文中对极智嘉(Geek)给予了高度赞扬。CEVA表示&#xff0c;极智嘉不仅彻底颠覆了CEVA的工作环境&#xff0c;还充分保障了敬业员工的安全和人体工程学效率…

C#List转IList方法

最近工作中使用到了C#的List和IList。 这里参考百度上的资料&#xff0c;总结一下。 IList使用命名空间&#xff1a; using System.Collections; List<T>类:表示可通过索引访问的对象的强类型列表&#xff0c;提供用于对列表进行搜索、排序和操作的方法。 IList<T&…