一. 什么是Maven
- Maven是一个基于
项目对象模型
(Project Object Model, 简称POM)的Java项目管理和构建工具
。它通过使用POM文件、目录结构和集中存储库来简化项目的配置和依赖管理,使得开发者可以快速构建、管理和发布Java项目。 - Maven的主要功能包括自动化构建过程(如编译、测试、打包、发布等),提供标准化的项目结构和管理方式,以及管理项目的依赖。
二. Maven的核心概念
2.1坐标
Maven坐标是用于唯一标识项目中的构件(如jar包)的一组规则。这些规则包括了几个关键元素:groupId
、artifactId
、version
、packaging
和classifier
。
其中,groupId、version、artifactId是必须的,它们共同定义了一个项目的唯一标识符;packaging是可选的,它指定了构件的打包格式;classifier也是可选的,用来帮助定义构建输出的一些附属构件。示例如下:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>6.1.6</version>
</dependency>
元素 | 描述 |
---|---|
groupId | 定义当前模块隶属的实际Maven项目, 表示方式与Java包类似Maven项目隶属的实际项目,命名方式通常与域名反向一一对应。必须定义。 |
artifactId | 实际项目中的一个Maven项目(模块),推荐使用实际项目名称作为artifactId的前缀。必须定义。 |
version | Maven项目当前所处的版本。必须定义。 |
packaging | Maven项目的打包方式,打包方式通常与所生成构件的文件扩展名对应。当没有定义时,Maven会使用默认值jar。 |
classifier | 帮助定义构件输出的一些附属附件。注意,不能直接定义项目的classifier,因为附属构件不是项目直接默认生成的,而是由附加的插件帮助生成的。 |
2.2依赖
在pom中定义project下的dependencies元素可以包含一个或者多个dependency元素来声明一个或者多个项目依赖。
元素 | 描述 |
---|---|
groupId, artifactId, version | 依赖的基本坐标 |
type | 依赖的类型,对应于坐标的packaging,默认jar |
scope | 依赖的范围,用来控制依赖与三种classpath(编译classpath、测试classpath、运行classpath)的关系 |
optional | 标记依赖是否可选 |
exclusions | 用来排除传递性依赖 |
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>6.1.6</version>
<type>jar</type>
<scope>compile</scope>
<optional>false</optional>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
Maven提供了dependency插件可以对Maven项目依赖查看以及优化
2.3 依赖范围
- maven在编译项目主代码时需要使用一套classpath,编译项目主代码时需要用到的jar包会以依赖的方式被引入到classpath中。
- maven在编译和执行测试这两个阶段会使用不同的classpath。
- 依赖范围就是用来控制与这三种classpath(编译classpath,测试classpath,运行classpath)的关系。
Maven中有以下几种依赖范围:
依赖范围 | 含义 |
---|---|
compile | 编译依赖范围,默认范围。对于编译,测试,运行三种classpath都有效。 |
test | 测试依赖范围。只对于测试classpath有效,在编译主代码和运行主程序中不会被用到。例如junit |
provided | 已提供依赖范围。对于编译和测试classpath有效,但在运行时无效。例如servlet-api |
runtime | 运行时编译依赖,对于测试和运行classpath有效,但在编译主代码时无效。例如数据库驱动。 |
system | 系统依赖范围,和provided依赖范围完全一致,但必须通过systemPath显示指定依赖范围的路径,往往与本机系统绑定,谨慎使用 |
import | 导入依赖范围。不会对三种classpath有影响。 |
2.4 版本依赖顺序
Maven的版本依赖顺序主要遵循以下原则:
直接依赖优先于间接依赖: 如果一个项目直接依赖于某个库,那么这个库会优先于其他间接依赖被加载。这是因为直接依赖是项目明确声明的,而间接依赖可能是通过其他库间接引入的。
路径最短原则:当存在多个相同版本的依赖时,Maven会选择路径最短的依赖作为最终的依赖。这意味着从当前项目到该依赖的路径长度越短,该依赖就越优先被加载。
pom文件中声明的顺序:如果两个或更多的依赖具有相同的路径长度(即深度相同),那么Maven会根据pom文件中声明的顺序来决定使用哪个依赖。声明位置在最前面的依赖优先级最高。
父项目和子项目的覆盖规则:如果有父项目(parent pom)和子项目(child pom),子项目中的依赖声明将覆盖父项目中的相应声明。这允许在不同层次的项目中指定不同的依赖版本。
这些原则共同构成了Maven处理依赖关系的基本机制,帮助开发者有效地管理和解决依赖冲突问题。
2.5 生命周期
maven将其架构和结构的组织放置到了components.xml 配置文件中,该配置文件的路径是:apache-maven-${version}\lib\maven-core-${version}.jar\META-INFO\plexus\conponents.xml
文件中。
其中,我们可以看到关于default生命周期XML节点配置信息,一个项目的生命周期抽象成了23个阶段:
<component>
<role>org.apache.maven.lifecycle.Lifecycle</role>
<implementation>org.apache.maven.lifecycle.Lifecycle</implementation>
<role-hint>default</role-hint>
<configuration>
<id>default</id>
<phases>
<phase>validate</phase>
<phase>initialize</phase>
<phase>generate-sources</phase>
<phase>process-sources</phase>
<phase>generate-resources</phase>
<phase>process-resources</phase>
<phase>compile</phase>
<phase>process-classes</phase>
<phase>generate-test-sources</phase>
<phase>process-test-sources</phase>
<phase>generate-test-resources</phase>
<phase>process-test-resources</phase>
<phase>test-compile</phase>
<phase>process-test-classes</phase>
<phase>test</phase>
<phase>prepare-package</phase>
<phase>package</phase>
<phase>pre-integration-test</phase>
<phase>integration-test</phase>
<phase>post-integration-test</phase>
<phase>verify</phase>
<phase>install</phase>
<phase>deploy</phase>
</phases>
</configuration>
</component>
maven生命周期各个阶段的行为与maven默认行为:
-
mvn compile
让当前项目经历生命周期中的1-->7 阶段 :完成编译主源代码编译 -
mvn package
让当前项目经历生命周期中的1-->17阶段 :完成打包 -
mvn install
让当前项目经历生命周期中的1-->22阶段 :完成包安装到本地仓库 -
mvn deploy
让当前生命经历生命周期中的1-->23阶段 :完成包部署到中心库中
三. Maven仓库
对与maven的生命周期,引出了Maven仓库的概念。Maven仓库主要用于管理项目中所依赖的第三方库,这些库包括但不限于JAR文件、WAR文件、ZIP文件和POM文件等。通过Maven仓库,可以有效地管理和维护项目中的构件
(构件指的是任何的依赖、插件、项目输出的jar包)
3.1 本地仓库
- 本地仓库的默认目录是:/.m2/repository,如果用户需要自定义的仓库目录,编辑/.m2/settings.xml,设置localRepository即可。
- 默认情况下
~/.m2/settings.xml
是不存在的,可以从maven安装目录复制conf/settings.xml
文件再进行编辑。当然也可以直接修改conf/settings.xml文件,前者配置优先于后者。 - 一个构件只有在本地仓库中之后,才能由其他maven项目使用。
3.2 远程仓库
-
中央仓库就是一个默认的远程仓库,maven的安装文件自带了中央仓库的配置。Maven内置了远程公用仓库:
https://mvnrepository.com/
- 每个用户只有一个本地仓库,但是可以配置多个远程仓库。
- 可以修改settings.xml或者在pom文件,使用<repositories>元素来声明一个或多个远程仓库。
- 每个远程仓库都需要通过<repository>元素来定义,其中必须包含id、name和url三个属性。id是远程仓库的唯一标识,name是为了方便阅读而设置的名称,而url则是指向该仓库地址的URL
3.3 私服
- 搭建Maven私服主要有以下几种方式:最主流的是使用
Nexus
,除此之外还有Artifactory和Apache Archiva(不常用) - 私服是一种特殊的远程仓库,架设在局域网内的仓库服务,私服代理广域网上的远程仓库,供局域网内的maven用户使用。
- 当maven需要下载构件的时候,从私服请求,如果私服上不存在此构件,则从外部的远程仓库中下载,缓存在私服之后,再为maven下载请求提供服务。此外,一些无法从外部仓库中下载到的构件也能从本地上传到私服供大家使用。
- 使用私服能够带来如下好处:节省网络(外网)带宽、加速maven构建、部署第三方构建:特指一些构件不能从远程仓库中获得、 提供稳定性,增强控制、降低中央仓库的负荷等