「这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战」。
一、Maven简介
本文将分享关于Maven的学习,Maven是一个项目管理工具,将项目开发和管理过程抽象成一个项目对象模型(POM),用于项目构建、依赖管理、统一开发结构。Maven 曾是 Jakarta 项目的子项目,现为由 Apache 软件基金会主持的独立 Apache 项目。其优点是统一开发项目结构、统一jar包资源管理,避免资源冲突。缺点是有一定的学习成本、项目模块间通过pom互相依赖,新手不易理清相互之间的关系。做Java开发的都需要了解并使用Maven,让我们一起来学习Maven吧。
二、依赖管理
2.1 依赖传递
2.1.1 直接依赖
直接依赖指在当前项目中通过依赖配置建立的依赖关系。使用标签定义,比如common模块直接依赖log4j:
2.1.2 间接依赖
间接依赖指通过传递过来的依赖称为间接依赖。比如login依赖了common模块,common模块依赖了log4j,login模块也能使用log4j。
2.2 依赖传递冲突
2.2.1 路径优先
路径优先指当依赖中出现相同的资源时,层级越深,优先级越低,层级越浅,优先级越高。比如login模块依赖了common模块,common模块依赖了log4j的1.2.13版本,login模块在pom中又直接依赖了log4j的1.2.14版本,那么根据路径优先原则会使用log4j的1.2.14版本。
2.2.2 声明优先
声明优先指当资源在相同层级被依赖时,配置顺序靠前的覆盖 配置顺序靠后的。比如common模块配置了log4j的1.2.13版本,user模块配置了log4j的1.2.14版本,根据声明优先原则,优先使用1.2.14版本。
2.2.3 特殊优先
特殊优先指当同级配置了相同资源的不同版本,后配置的覆盖先配置的。比如common模块同时配置了log4j的1.2.13版本和1.2.14版本,根据特殊优先原则,1.2.14版本生效。
2.2.4 可选依赖
可选依赖指对外隐藏当前所依赖的资源。比如common模块配置了lombok,但不想让其他模块使用,这个时候我们可以使用true来隐藏该依赖。
2.2.5 排除依赖
当我们不想使用其他模块的依赖资源时,可以手动排除依赖。比如common模块依赖了lombok,login依赖了common,这个时候login模块间接的依赖了lombok,我们通过排除该依赖。
2.3 依赖范围
依赖的jar包默认情况可以在任何地方使用,可以通过scope标签设定其作用范围。 作用范围:
- 主程序范围有效(main文件夹范围内)
- 测试程序范围有效(test文件夹范围内)
- 是否参与打包(package指令范围内)
2.3.1 scope
Maven中使用 scope 来指定当前包的依赖范围和依赖的传递性
scope标签可选值:
- compile:默认依赖有效范围
- provided:编译、测试时有效,运行时无效
- runtime:运行、测试时有效,编辑时无效
- test:测试时有效
- system:编译、测试时有效,运行时无效。和provided的区别是,使用system范围的依赖时必须通过systemPath元素显式地指定依赖文件的路径
三、生命周期与插件
3.1 生命周期
Maven 构建生命周期定义了一个项目构建跟发布的过程,简单说就是运行的阶段。
Maven对项目构建的生命周期划分为三种:
- clean:项目清理工作
- default或build:核心工作,比如项目编译、测试、打包、部署
- site:产生报告、发布站点
3.2 插件
插件与生命周期内的阶段绑定,执行到对应生命周期时执行对应的插件功能。默认Maven在各个生命周期上绑定有预设的功能,通过插件还可以自定义功能。
常用的插件:
- clean:构建之后清理目标文件并删除目标目录
- compiler:编译Java源文件
- surefile:运行JUnit单元测试,创建测试报告
- jar:从当前工程中构建JAR文件
- war:从当前工程中构建WAR文件
- javadoc:为工程生成Javadoc
- antrun:从构建过程的任意一个阶段中运行一个ant任务的集合
我们可以使用build标签定义构建项目,在IDEA右侧可以方便的使用插件。
还可以点击M图标,打开列表能看到更多的插件命令。
四、聚合与继承
4.1 聚合
聚合用于快速构建Maven工程,一次构建多个模块。聚合模块需要写上pom,否则会默认打成jar包,聚合操作的模块最终执行顺序和模块间的依赖有关系,和配置顺序无关。
4.2 继承
通过继承可以实现在子工程中沿用父工程中的配置,在子工程中声明其父工程坐标与对应的位置。子工程不用声明依赖的版本号,会使用父工程配置的依赖版本号,如果定义版本号则使用自己定义的版本号。能够解决各个模块版本不统一的问题。需要注意的是:父工程配置完依赖后,子工程也需要配置依赖,只是不用声明依赖版本号。
<!--定义该工程的父工程-->
<parent>
<groupId>com.pzc</groupId>
<artifactId>project</artifactId>
<version>1.0-SNAPSHOT</version>
<!--填写父工程的pom文件-->
<relativePath>../project/pom.xml</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
在父工程中定义依赖管理,声明哪些依赖可以被使用。
<!--声明此处进行依赖管理-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
</dependencies>
</dependencyManagement>
4.3 继承与集合的区别
作用:
聚合用于快速构建项目
继承用于快速配置
相同点:
聚合与继承的pom.xml文件打包方式都是pom,可以将两种关系制作到同一个pom文件中
聚合与继承属于设计模块,并没有实际的模块内容
不同点:
聚合是在当前模块中配置关系,聚合可以感知到参与聚合的模块有哪些
继承是在子模块中配置关系,父模块无法感知哪些子模块继承了自己
五、属性
使用标签可以定义一个或者多个属性,在pom文件中的任意位置通过${属性名}的方式使用该属性值,这样就能消除重复和统一管理。属性分为自定义属性、内置属性(version、basedir)、Setting属性(setting.localRepository)、Java系统属性 、环境变量属性。
接下来我们用自定义属性来设置下版本号。
<!--自定义属性-->
<properties>
<spring-version>5.3.0</spring-version>
</properties>
<!--声明此处进行依赖管理-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
</dependencyManagement>
六、版本管理
版本管理使用标签1.0.0-SNAPSHOT进行设置。
6.1 工程版本
SNAPSHOT(快照版本):快照版本会随着开发进展不断更新
RELEASE(发布版本):发布版本,如果功能进行更新,也不会改变当前发布版本内容工程版本号约定
6.2 约定规范
约定规范:
<主版本>.<次版本>.<增量版本>.<里程量版本>
主版本:表示项目重大架构变更
次版本:表示有较大功能增加和变化
增量版本:表示有重大漏洞的修复
里程碑版本:表示一个版本的里程碑,和下一个正式版本相比不太稳定
范例:
2.0.0.1.RELEASE
七、总结
Maven的知识点并不算太多,但pom标签很多,我们先掌握常用的标签即可,其他标签需要我们主动去尝试和使用。关于Maven的学习到这里就结束了,如果对你有些许帮助请点赞收藏。
入门篇:Maven入门学习