Maven的进阶

目录

一、pom.xml文件

二、坐标

[2.1 坐标的概念](#2.1 坐标的概念)

[2.2 坐标的意义](#2.2 坐标的意义)

[2.3 坐标的含义](#2.3 坐标的含义)

[2.4 在IDEA中查看项目的坐标](#2.4 在IDEA中查看项目的坐标)

三、依赖

[3.1 依赖的意义](#3.1 依赖的意义)

[3.2 依赖的使用](#3.2 依赖的使用)

[3.3 第三方依赖的查找使用方法](#3.3 第三方依赖的查找使用方法)

[3.4 依赖的范围](#3.4 依赖的范围)

[3.5 依赖传递和可选依赖](#3.5 依赖传递和可选依赖)

[3.5.1 依赖传递](#3.5.1 依赖传递)

[3.5.2 依赖范围对传递依赖的影响](#3.5.2 依赖范围对传递依赖的影响)

[3.5.3 依赖阻断](#3.5.3 依赖阻断)

[3.5.4 可选依赖](#3.5.4 可选依赖)

四、仓库

[4.1 仓库的概念](#4.1 仓库的概念)

[4.2 依赖搜索顺序](#4.2 依赖搜索顺序)

五、Maven的继承和聚合

[5.1 继承的意义](#5.1 继承的意义)

[5.2 可继承的POM元素](#5.2 可继承的POM元素)

[5.3 搭建一个Maven聚合模块基本框架](#5.3 搭建一个Maven聚合模块基本框架)

[5.4 继承的依赖管理](#5.4 继承的依赖管理)

[5.5 聚合管理](#5.5 聚合管理)


一、pom.xml文件

就像 Make 的 MakeFile、Ant 的 build.xml 一样,Maven 项目的核心是 pom.xml。POM( Project Object Model,项目对象模型 ) 定义了项目的基本信息,用于描述项目如何构建,声明项目依赖,等等

除了直接打开项目文件,也可以使用pom.xml来打开文件

二、坐标

2.1 坐标的概念

在 Maven 中坐标是构件的唯一标识,Maven 坐标的元素包括 groupIdartifactIdversion 、packaging、classifier。上述5个元素中,groupId、artifactId、version 是必须定义的,packaging 是可选的 ( 默认为 jar )。

2.2 坐标的意义

  • Maven世界拥有大量构建,我们需要找一个用来唯一标识一个构建的统一规范
  • 拥有了统一规范,就可以把查找工作交给机器

2.3 坐标的含义

groupId:组织标识,一般为:公司网址的反写+项目名
artifactId:项目名称,一般为:项目名-模块名
version:版本号 形式为0.0.1-SNAPSHOT:

第一个 0 表示大版本号,第二个 0 表示分支版本号,第三个 0 表示小版本号

SNAPSHOT -- 快照版本,ALPHA -- 内侧版本,BETA -- 公测版本,RELEASE -- 稳定版本,GA -- 正式发布
packaging:打包的方式,如:pom, jar, maven-plugin, ejb, war, ...(默认为jar包)
clissifier:用来帮助定义构件输出的一些附属构件。

2.4 在IDEA中查看项目的坐标

① 当前项目的坐标

② 引入依赖包的坐标

三、依赖

3.1 依赖的意义

当编写Java代码时,我们总是需要一些库,例如,做单元测试我们需要JUnit库,对于更大的项目,我们可能需要创建自己的库并在不同的部分使用它的项目,每个外部JAR可能还依赖于其他外部JAR文件等,以递归方式下载所有这些外部依赖JAR文件并确保下载正确的版本是一项巨大的任务,而且不同的项目需要不同版本的库, 保持项目最新的库JAR文件的正确版本不是一个容易的事。

但这些任务如今都可以通过Maven来帮助我们进行管理实现,通过在POM文件中的dependencies元素内指定依赖关系,Maven可以将它们下载下来并存放在我们的本地Maven仓库中,不再需要我们去手动下载更换不同的外部文件。

3.2 依赖的使用

例如我们的项目需要进行单元测试,则需要使用到junit-4.9.jar包,使用maven引用该依赖的方式如下:

\

属性说明:

三维坐标 :引用依赖包的三维坐标(即groupIdartifactIdversion),用来定位该依赖包

scope: 控制该依赖包在什么情况下会被加到 classpath 中

3.3 第三方依赖的查找使用方法

我们在不确定所需引用的第三方依赖包的坐标时,通过maven的中央仓库进行查找, 网址: https://mvnrepository.com/

这里以junit为例:

① 输入搜索名称,选择需要的依赖包打开

② 向下滑动,找到需要的依赖包版本,点击打开

③ 复制需要的依赖包maven坐标到pom.xml中即可

3.4 依赖的范围

Maven项目在开发工程中有三套classpath

主代码:main下面的都是主代码在编译的时候的依赖

测试代码:test下是测试代码编译的时候的依赖

运行时:main代码在运行的时候对包的依赖

依赖范围的使用,通过在引用第三方依赖时的<scope></scope>标签进行设置,例如:

共 6 种 scope,包括:compileprovidedruntimetest 、system、import。例如上图的junit,只在测试中使用,则选择test即可,如果不选择则默认为compile

  • **Compile:**编译依赖范围。默认使用此依赖范围,其下的maven依赖,对于编译,测试,运行classpath都有效
  • **Test:**测试依赖范围。只对测试classpath有效,编译主代码或运行项目时无法使用此依赖。典型例子如junit
  • **Provided:**已提供依赖范围。其对于编译与测试classpath有效,运行时无效。如在web开发时,只有在编译和测试时才用到servlet-api,将其设置为此范围,在运行时servlet-api由web容器提供,无须依赖。并且在打war包时,此范围的依赖不会打在WEB-INF/lib下
  • **Runtime:**运行时依赖范围。与provided相对,运行时classpath有效。典型例子如jdbc

通过下图更直观了解一下各scope作用范围:

3.5 依赖传递和可选依赖

3.5.1 依赖传递

应用场景:

第一直接依赖: HelloFriend项目依赖Hello项目

第二直接依赖: MakeFriend项目依赖HelloFriend项目

可以看到,MakeFriend明明只依赖HelloFriend但是把Hello也依赖了进来,这是因为HelloFriend依赖Hello,如下图:

因为依赖传递,所以导致MakeFriend依赖HelloFriend的同时把Hello也依赖了进来

3.5.2 依赖范围对传递依赖的影响

大致内容就这个图,第一次看不理解也无所谓,后边用多了就知道了

3.5.3 依赖阻断

按上述步骤进行完后,可以发现,本该由于依赖传递而应该在MakeFriend中的Hello依赖不见了,这就是依赖阻断的作用,也就是暴力阻断,平常写代码时不推荐使用这种方法,因为每次使用都要去重新install,而且如果有别的项目需要用到HelloFriend下的Hello依赖时,会与不需要用到Hello依赖而使用依赖阻断的项目互相冲突,因此更多的是使用下面所讲的可选依赖

3.5.4 可选依赖

如果我们需要在依赖中明确的排除掉某一依赖,则可以使用exclusion属性,排除掉引用的依赖,如图:

此时刷新Maven项目

我们可以发现,Hello依赖已经不见了,使用这种方式排除依赖传递更加方便,同时也可以防止与别的项目冲突

四、仓库

4.1 仓库的概念

Maven 仓库是项目中依赖的第三方库,这个库所在的位置叫做仓库

在 Maven 中,任何一个依赖、插件或者项目构建的输出,都可以称之为构件

Maven 仓库能帮助我们管理构件(主要是JAR),它就是放置所有JAR文件(WAR,ZIP,POM等等)的地方

仓库的类型有:

  • 本地(local)
  • 中央(central)
  • 远程(remote)

4.2 依赖搜索顺序

(上面图中是依赖引入顺序,把箭头反过来引入依赖改成搜索依赖就是依赖搜索顺序)

maven会先去从本地仓库去搜索依赖,如果没有找到再去公司的私服去搜索依赖(如果没有建立私服则没有这一步),最后再去maven的中央仓库去找(公司的私服还充当一个代理服务器,当私服上没有 jar 包会从互联网中央仓库自动下载),如果这些位置都没有找到,说明该依赖不存在或被加密了,maven此时则会报错

五、Maven的继承和聚合

5.1 继承的意义

继承就是避免重复,maven的继承也是这样,它还有一个好处就是让项目更加安全。比如我们在项目开发的过程中,可能多个模块独立开发,但是多个模块可能依赖相同的公共模块,比如说每个模块都需要javase-utils,在编译的时候,maven-compiler-plugin插件也要被引入,maven仓库地址以及发布目录都是相同的配置。我们可以使用Maven的继承功能,把公共的配置信息写到父模块中,子模块只要继承了该父模块,也会继承父模块的配置信息。

5.2 可继承的POM元素

groupId :项目组 ID ,项目坐标的核心元素;

version :项目版本,项目坐标的核心元素;

description :项目的描述信息;

organization :项目的组织信息;

inceptionYear :项目的创始年份;

url :项目的 url 地址

develoers :项目的开发者信息;

contributors :项目的贡献者信息;

distributionManagerment :项目的部署信息;

issueManagement :缺陷跟踪系统信息;

ciManagement :项目的持续继承信息;

scm :项目的版本控制信息;

mailingListserv :项目的邮件列表信息;

properties :自定义的 Maven 属性;

dependencies :项目的依赖配置;

dependencyManagement :醒目的依赖管理配置;

repositories :项目的仓库配置;

build :包括项目的源码目录配置、输出目录配置、插件配置、插件管理配置等;

reporting :包括项目的报告输出目录配置、报告插件配置等。

5.3 搭建一个Maven聚合模块基本框架

该项目包含前台,后台,图片服务器,core(公共模块)四个模块,被parent父类统一管理

① 创建一个MavenJava项目作为父类

因为不需要写代码,所以可以直接将父类中的src文件夹删掉

② 创建core公共模块(MavenJava项目)

可以看到,子类模块的pom.xml中没有groupId了,取而代之的是parent(properties模块也可以删掉,由父类pom.xml统一进行管理

parent的pom.xml中也多了一个modules

③ 创建前台模块(JaveWeb项目)

检查maven路径是否设置正确,检查完毕后点击完成即可:

查看portal的pom.xml文件

④ 搭建后台模块(JavaWeb项目)

步骤同③

搭建图片服务器模块(JavaWeb项目)

步骤同③

创建完成后目录如下图:

至此,基础框架已搭建完毕

5.4 继承的依赖管理

在properties中记录使用的版本号(该部分里面只定义版本),使用如下图所示:

此时在父类的pom.xml文件中定义dependencies,在父类中导入的依赖,所有子类中都会有,如下图:

但是父类中我们不写代码,因此父类不需要有依赖,而且也不是每个项目都需要该依赖,所以这样设置会导致大量资源的浪费

这时就需要用到dependencyManagement,将dependencies中内容移到dependencyManagement中,然后刷新maven项目,如下图:

此时我们发现父类中没有引入该依赖,子类也全部没有引入该依赖

然后再去子类的pom文件中定义dependencies,dependency中引入依赖不需要再写版本号,因为父类中已经引入版本号,只需要写groupId和artifactId即可,如下图:

此时我们可以发现,只有定义了dependency的子类引入了该依赖,同时其版本也是继承自父工程,与父类的pom.xml定义的版本号一致

以上就是继承的依赖管理的内容

5.5 聚合管理

我们在平时的开发中,项目往往会被划分为好几个模块,比如common公共模块、system系统模块、log日志模块、reports统计模块、monitor监控模块等等,而如果一个一个的去install则会过于麻烦,这时我们就会出现这么一个需求,我们需要一次构件多个模块,而不是每个模块都去mvn install,因此就有了聚合管理。

以上面的父子项目为例,当我们对parent进行mvn install时,maven会对core,portal,console和file项目均进行install操作:

从上图可以看到,在对parent进行install操作时,其子类也会全部被install

相关推荐
草莓base2 分钟前
【手写一个spring】spring源码的简单实现--bean对象的创建
java·spring·rpc
Karoku06622 分钟前
【企业级分布式系统】ELK优化
运维·服务器·数据库·elk·elasticsearch
drebander26 分钟前
使用 Java Stream 优雅实现List 转化为Map<key,Map<key,value>>
java·python·list
乌啼霜满天24930 分钟前
Spring 与 Spring MVC 与 Spring Boot三者之间的区别与联系
java·spring boot·spring·mvc
tangliang_cn35 分钟前
java入门 自定义springboot starter
java·开发语言·spring boot
程序猿阿伟36 分钟前
《智能指针频繁创建销毁:程序性能的“隐形杀手”》
java·开发语言·前端
Grey_fantasy1 小时前
高级编程之结构化代码
java·spring boot·spring cloud
弗锐土豆1 小时前
工业生产安全-安全帽第二篇-用java语言看看opencv实现的目标检测使用过程
java·opencv·安全·检测·面部
Elaine2023911 小时前
零碎04 MybatisPlus自定义模版生成代码
java·spring·mybatis
小小大侠客1 小时前
IText创建加盖公章的pdf文件并生成压缩文件
java·pdf·itext