介绍
Maven是Apache旗下的一款开源的项目管理工具,使用了项目对象模型(POM-Project Object Model)的概念。
在Maven中,用户仅通过一小段描述信息就可以实现项目的构建、报告、文档管理、导包、项目拆分等效果。每个项目都相当于一个对象,对象之间的关系囊括了依赖、继承还有聚合。核心配置文件为pom.xml,用户可以通过编写这个文件,来实现上述的各种操作。
同时,Maven还提供了各类丰富的插件,包括但不限于项目打包、测试、资源拷贝及Tomcat等。
下载与安装
下载
点击downloads

下载二进制压缩包

安装
无需安装,直接将下载的二进制压缩包解压即可。
目录结构

文件配置
文件位置在conf目录下的settings.xml
XML
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.2.0 https://maven.apache.org/xsd/settings-1.2.0.xsd">
<!-- 本地仓库绝对路径 -->
<localRepository></localRepository>
<!-- 镜像仓库列表 -->
<mirrors>
<!-- 阿里云镜像仓库 -->
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
<!-- 配置列表 -->
<profiles>
<!--
配置JDK版本,可以在这里配置也可以在项目的pom.xml中进行配置
这里配置:所有被Maven管理的项目都使用配置的JDK版本
pom.xml中配置:只有该项目使用该版本的JDK
都配置:pom.xml配置生效
-->
<profile>
<id>jdk-21</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>21</jdk>
</activation>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<maven.compiler.comilerVersion>21</maven.compiler.comilerVersion>
</properties>
</profile>
</profiles>
</settings>
仓库
中央仓库(Central Repository)
Maven官方服务器,里面存放了市面上流行的绝大多数jar。允许用户注册后,上传自己的项目到官方服务器。网址在国外,经常访问不了。
镜像仓库(Mirror Repository)
另一台备份/复制了中央仓库的服务器,国内开发者大多使用阿里云镜像或华为云镜像。由于中央仓库的访问速度太慢,使用镜像仓库可以大大提升资源的下载速度。
本地仓库(Local Repository)
使用本机的文件夹作为本地仓库,用来缓存远程下载,也包含了项目尚未发布的临时构件。
依赖加载流程

标签
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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<!-- 指定pom默认版本。Maven2.x、Maven3.x中modelVersion必须是4.0.0 -->
<modelVersion>4.0.0</modelVersion>
<!-- 父项目坐标 -->
<parent>
<!-- 一般是公司域名倒写,如:com.sumlv -->
<groupId></groupId>
<!-- 一般是项目(jar)名 -->
<artifactId></artifactId>
<!-- 版本号 -->
<version></version>
</parent>
<!-- 当前项目坐标 -->
<groupId></groupId>
<artifactId></artifactId>
<version></version>
<!-- 项目类型 -->
<!-- jar:打包时会将项目打包为一个.jar。主要打包java文件 -->
<!-- war:打包时会将项目打包为一个.war。打包时会包含src和webapp目录的内容 -->
<!-- pom:当项目是父项目时使用。表示该项目除了pom.xml外不会再有其他任何类或资源文件 -->
<packaging></packaging>
<!-- 属性列表 -->
<properties>
<!-- 标签名可自定义,后续以${标签名}的方式引用标签值 -->
<></>
</properties>
<!-- 第三方依赖列表 -->
<dependencies>
<!-- 依赖 -->
<dependency>
<!-- 坐标 -->
<groupId></groupId>
<artifactId></artifactId>
<version></version>
<!-- 当前依赖的域(域:有效范围) -->
<!-- compile:默认值,表示该依赖参与项目的编译、打包、测试及发布,属于强依赖 -->
<!-- provided:编译时生效,最终打包时不会包含该依赖 -->
<!-- runtime:运行时生效。编译时不参与,但参与项目的测试及打包 -->
<!-- test:测试时生效,包中的类只能在src/main/test中使用。常用于junit -->
<!-- system:类似provided,但是需要结合systemPath属性。表示该依赖不是来源于本地库,而是来源于其他目录 -->
<scope></scope>
<!-- 需要排除的依赖列表 -->
<exclusions>
<!-- 需要排除的依赖 -->
<exclusion>
<!-- 依赖坐标。无需添加版本号,因为无论什么版本都会被排除 -->
<groupId></groupId>
<artifactId></artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<!-- 构建配置 -->
<build>
<!-- 插件列表 -->
<plugins>
<!-- 插件 -->
<plugin>
<!-- 插件坐标 -->
<groupId></groupId>
<artifactId></artifactId>
<version></version>
<!-- 其他配置,略...... -->
</plugin>
</plugins>
<!-- 资源拷贝列表 -->
<!--
Maven项目中约定src/main/java路径下只编译.java文件,src/main/resources路径下只编译资源文件。
如果由于某些原因必须在src/main/java中放置一些非.java文件(如:MyBatis),并且希望Maven去编译这些文件,就必须配置资源拷贝插件。
一旦配置了其他资源目录,就需要把src/main/resources目录也配置进去。因为一旦指定了其他目录,就不会再从src/main/resources路径下编译资源文件了
-->
<resources>
<!-- 资源 -->
<resource>
<!-- 资源路径 -->
<directory></directory>
<!-- 具体资源配置列表 -->
<includes>
<!-- 具体资源配置,如:**/*.txt -->
<!-- **:任意子目录 -->
<!-- *.txt:任意名称的txt文件 -->
<include></include>
</includes>
</resource>
</resources>
</build>
</project>
生命周期
Maven有三套相互独立的生命周期(Lifecycle),分别为Clean、Default和Site。生命周期的每个阶段必须按照严格的顺序执行,当然我们可以执行任意一个阶段,但是每次都会从第一个阶段开始执行。比如执行test阶段时,Maven会从validate开始,直到test结束。
每个阶段的操作可以通过maven命令来执行,也可以使用IDEA集成后提供的图形界面来完成。通过图形界面的方式相对比较简单,直接选择相对应的阶段双击运行即可。
Clean (做一些清理工作)
bash
# 删除target目录,清理之前所有编译的内容。手动删除target目录和运行此命令是等效的
mvn clean
Default(构建的核心部分、编译、测试、打包、部署等)
bash
# 验证项目是否可用
mvn validate
# 编译项目,生成target目录
mvn compile
# 执行测试。执行时会自动运行src/test/java目录下所有*Test.java文件的所有测试单元
mvn test
# 打包项目
mvn package
# 发布项目。在构建环境中完成,将最终包复制到远程存储库用于与其他开发人员和项目共享
mvn deploy
# 校验包是否正确
mvn verify
# 将包安装到本地存储库中,作为本地其他项目的依赖项
mvn install
Site(生成项目报告、站点、发布站点)
bash
# 生成项目报告、站点、发布站点,需要添加以下插件才能使用
# <build>
# <plugins>
# <plugin>
# <groupId>org.apache.maven.plugins</groupId>
# <artifactId>maven-project-info-reports-plugin</artifactId>
# <version>2.7</version>
# </plugin>
# </plugins>
# </build>
mvn site
重复依赖问题
最短路径优先原则
项目依赖关系树中路径最短的版本会被使用。
举个例子:A、B、C三个依赖之间的关系是A > B > C > D(2.0) 和A > E > D(1.0),那么D(1.0)最终会被使用,因为A通过E到D的路径更短。
最先声明原则
当依赖路径长度是一样的的时候,最短路径优先原则将不能解决问题。
在maven2.0.8及之前的版本中,最终依赖的版本是不确定的。但是从maven2.0.9开始,为了尽可能避免不确定性,maven定义了最先声明原则。在依赖路径长度相等的前提下,在POM文件中位置最靠前的依赖会被解析使用。
当然我们也可以使用<exclusion>把某些依赖直接排除掉
项目关系
依赖
就是单纯的添加坐标后的调用关系,这里不做过多赘述。
继承
项目间的继承只能是单继承。
父项目通常为pom类型,其中不写java代码,只用于子工程的管理。其原因是:父项目的存在就是为了让子项目继承其pom.xml中的坐标资源,而不是使用父项目的代码,而且就算父项目写了代码也继承不了。
继承父项目前,需要先引入父项目的坐标,所以父项目一定要先打包放入本地库才可以。
聚合
在实际开发中,一个大项目可以被拆分成不同的小项目,项目之间往往都有密切的关联。当我们想要在同一个窗口中创建多个项目,且子项目之间依赖不需要逐个install时(聚合项目直接使用父项目install一次就行)就可以使用聚合,使用聚合可以让项目在管理更加方便的同时还能保证所有子项目都是独立的。
聚合关系的前提是继承,所以聚合项目都会包含继承的特性。
继承与依赖的区别
依赖是为了调用代码,继承是为了使用父项目的资源坐标,目的不同。
被依赖的项目类型只能是jar。其原因是:依赖的目的是为了用java代码,而pom项目没有java代码。web项目除了java代码还有web资源,我们不需要依赖那些网页资源。
聚合和继承的区别
聚合关系的父项目一定是pom,而继承关系中父项目可以是jar、war、pom。
聚合关系的父项目会包含<modules>标签,写明所有的子项目。而继承关系中父项目不需要任何特殊处理。
聚合关系的子项目之间依赖只需要把父项目install一次就行。继承关系的子项目使用父项目需要将父项目install才能使用。