Maven项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的项目管理工具软件。

Maven 除了以程序构建能力为特色之外,还提供高级项目管理工具。由于 Maven 的缺省构建规则有较高的可重用性,所以常常用两三行 Maven 构建脚本就可以构建简单的项目。由于 Maven 的面向项目的方法,许多 Apache Jakarta 项目发文时使用 Maven,而且公司项目采用 Maven 的比例在持续增长。

参考文章:Maven基础&MyBatis

Maven简介

Maven是专门用于管理和构建Java项目的工具。

传统项目管理缺点:

  • jar包版本不统一、不兼容
  • 工程升级维护过程操作繁琐

Maven介绍:

Maven 的本质是一个项目管理工具,将项目开发和管理过程抽象成一个项目对象模型(POM)。

maven是用java语言写的,它管理的项目都以面对对象形式设计,最终把一个项目看成一个对象,即POM。

**POM:**(Project Object Model):项目对象模型

作用和功能

作用:

  • 项目构建:提供标准的、跨平台的自动化项目构建方式
  • 依赖管理:方便快捷的管理项目依赖的资源(jar包),避免资源间的版本冲突问题
  • 统一开发结构:提供标准的、统一的项目结构

功能:Maven是专门用于管理和构建Java项目的工具,它的主要功能有:

  • 提供了一套标准化的项目结构

    每一个开发工具(IDE)都有自己不同的项目结构,它们互相之间不通用。

    而Maven提供了一套标准化的项目结构,所有的IDE使用Maven构建的项目完全一样,所以IDE创建的Maven项目可以通用。

  • 提供了一套标准化的构建流程

    编译,测试,打包,发布……

  • 提供了一套依赖管理机制

    Maven使用标准的坐标配置来管理各种依赖, 只需要简单的配置就可以完成依赖管理

Maven模型

  • 项目对象模型pom (Project Object Model)
  • 依赖管理模型(Dependency)
  • 插件(Plugin)

image-20250728212853171

项目对象模型pom就是将我们自己抽象成一个对象模型,有自己专属的坐标,是唯一标识。

项目对象模型pom通过xml格式保存的pom.xml文件。该文件用于管理:源代码、配置文件、开发者的信息和角色、问题追踪系统、组织信息、项目授权、项目的url、项目的依赖关系等等。

1
2
3
<groupId>org.example</groupId>
<artifactId>ReviewTest</artifactId>
<version>1.0-SNAPSHOT</version>

依赖管理模型则是使用坐标来描述当前项目依赖哪些第三方jar包

1
2
3
4
5
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.3.4</version>
</dependency>

项目管理模型和依赖管理模型结合起来,体现Maven方便的依赖管理。

构建生命周期和插件部分用来完成 标准化构建流程

如我们需要编译,Maven提供了一个编译插件供我们使用。我们需要打包,Maven就提供了一个打包插件提供我们使用等。

仓库

Maven用坐标配置管理依赖。

依赖jar包则其实存储在本地仓库中,项目运行时从本地仓库中拿需要的依赖jar包。

  • 本地仓库:自己电脑上存储资源的仓库(是个目录),连接远程仓库获取资源
  • 中央仓库:由Maven团队维护的全球唯一的仓库,Maven团队维护,存储所有资源的仓库
  • **远程仓库(私服)**:一般由公司团队搭建的私有仓库。部门/公司范围内存储资源的仓库,从中央仓库获取资源

私服的作用:

  • 保存具有版权的资源,包含购买或自主研发的jar。中央仓库中的jar都是开源的,不能存储具有版权的资源
  • 一定范围内共享资源,仅对内部开放,不对外共享

当项目中使用坐标引入对应依赖jar包后,首先会查找本地仓库中是否有对应的jar包:

  • 如果有,则在项目直接引用;
  • 如果没有,则去中央仓库中下载对应的jar包到本地仓库。

image-20250728213201201

如果还可以搭建远程仓库,将来jar包的查找顺序则变为:

本地仓库 –> 远程仓库–> 中央仓库

image-20250728213219867

Maven 坐标详解

什么是坐标?

  • Maven 中的坐标是资源的唯一标识
  • 使用坐标来定义项目或引入项目中需要的依赖

所有坐标官网(需要梯子):Maven Repository

Maven 坐标主要组成

groupId:定义当前Maven项目隶属组织名称(通常是域名反写,例如:com.itheima)

artifactId:定义当前Maven项目名称(通常是模块名称,例如 order-service、goods-service)

version:定义当前项目版本号

scope:范围,像Servlet、jsp依赖都需要设置范围为provided

1
2
3
4
5
6
7
8
9
10
11
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<!--
此处为什么需要添加该标签?
provided指的是在编译和测试过程中有效,在运行时无效,最后生成的war包时不会加入
因为Tomcat的lib目录中已经有servlet-api这个jar包,如果在生成war包的时候生效就会和Tomcat中的jar包冲突,导致报错
-->
<scope>provided</scope>
</dependency>

注意:

  • 上面所说的资源可以是插件、依赖、当前项目。
  • 我们的项目如果被其他的项目依赖时,也是需要坐标来引入的。

Maven基本使用

Maven常用命令

compile :编译,生成target目录

clean:清理,删除target目录

test:测试,执行test文件下测试代码

package:打包,将当前项目打包成的jar包

install:安装,将当前项目打成jar包,并安装到本地仓库

image-20250728213443172

编译命令 mvn compile

首次编译会先从阿里云(之前conf/settings.xml配置了阿里云私服)下载编译需要插件的jar包,在本地仓库(之前conf/settings.xml配置了本地仓库位置)也能看到下载好的插件。

在项目下会生成一个 target 目录,里面保存编译后的字节码文件。

清理命令 mvn clean

  • 从阿里云下载清理需要的插件jar包
  • 删除项目下的 target 目录

Maven 生命周期

简洁版:

  • clean:清理上次构建结果
  • valide:校验工程信息是否正确
  • comple:编译工程
  • test:执行工程测试流程(标注的test的程序)
  • package:打包工程
  • verify:验证包的有效性
  • install:安装包到本地仓库
  • deploy:推送包到远程仓库

Maven 构建项目生命周期描述的是一次构建过程经历经历了多少个事件

Maven 对项目构建的生命周期划分为3套:

  • clean :项目清理的处理,移除所有上一次构建生成的文件。
  • default(或 build) :核心工作,例如编译,测试,打包,安装等。
  • site : 产生报告,发布站点等。这套生命周期一般不会使用。

Clean 生命周期

执行 mvn post-clean 命令时,Maven 调用 clean 生命周期,它包含以下阶段:

  • pre-clean:执行一些需要在clean之前完成的工作
  • clean:移除所有上一次构建生成的文件
  • post-clean:执行一些需要在clean之后立刻完成的工作

default生命周期

阶段 处理 描述
验证 validate 验证项目 验证项目是否正确且所有必须信息是可用的
编译 compile 执行编译 源代码编译在此阶段完成
测试 Test 测试 使用适当的单元测试框架(例如JUnit)运行测试。
包装 package 打包 创建JAR/WAR包如在 pom.xml 中定义提及的包
检查 verify 检查 对集成测试的结果进行检查,以保证质量达标
安装 install 安装 安装打包的项目到本地仓库,以供其他项目使用
部署 deploy 部署 拷贝最终的工程包到远程仓库中,以共享给其他开发人员和工程

注意:

  • 打包前先clean是好习惯,能够保证上一次构建的输出不会影响到本次构建。
  • 同一套生命周期内,执行后边的命令,前面的所有命令会自动执行。例如执行安装会先执行打包。

site构建生命周期:

  • pre-site:执行一些需要在生成站点文档之前完成的工作
  • site:生成项目的站点文档
  • post-site: 执行一些需要在生成站点文档之后完成的工作,并且为部署做准备
  • site-deploy:将生成的站点文档部署到特定的服务器上

pom文件配置编码及JDK版本

在pom.xml配置如下代码,适用于项目要在不同项目移动:

1
2
3
4
5
6
7
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<java.version>11</java.version>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>

Maven依赖管理

依赖概述

依赖指当前项目运行所需的jar,一个项目可以设置多个依赖。

groupId:依赖所属群组id。

artifactId:依赖所属项目id。

version:依赖版本号。

scope:依赖生效范围。

optional:为true时是可选依赖,指对外隐藏当前所依赖的资源——不透明。设置后其他依赖引用本项目时候将无法看到这个依赖。控制别人能不能看到你用到你。

exclusions-exclusion:排除依赖指主动断开依赖的资源,被排除的资源无需指定版本。控制你引用的项目中需要排除的依赖。

依赖范围scope

依赖的jar默认在任何地方使用,通过scope便签设定其范围。

通过设置坐标的依赖范围(scope),可以设置对应jar包的作用范围:编译环境、测试环境、运行环境。

如下图所示给 junit 依赖通过 scope 标签指定依赖的作用范围。 那么这个依赖就只能作用在测试环境,其他环境下不能使用。

1
2
3
4
5
6
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>

依赖范围scope可取值:

依赖范围 编译classpath 测试classpath 运行classpath 例子
compile Y Y Y logback
test - Y - Junit
provided Y Y - servlet-api
runtime - Y Y jdbc驱动
system Y Y - 存储在本地的jar包

配置后可以在依赖中看到:org.mybatis:mybatis:3.5.3 (runtime)

依赖具有传递性

直接依赖:在当前项目中通过依赖配置建立的依赖关系

间接依赖:被资源的资源如果依赖其他资源,当前项目间接依赖其他资源

依赖传递冲突问题

路径优先:当依赖中出现相同的资源时,层级越深,优先级越低,层级越浅,优先级越高

声明优先:当资源在相同层级被依赖时,配置顺序靠前的覆盖配置顺序靠后的

特殊优先:当同级配置了相同资源的不同版本,后配置的覆盖先配置的

可选依赖optional

可选依赖指对外隐藏当前所依赖的资源——不透明

1
2
3
4
5
6
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<optional>true</optional>
</dependency>

排除依赖exclusions-exclusion

排除依赖指主动断开依赖的资源,被排除的资源无需指定版本

1
2
3
4
5
6
7
8
9
10
11
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<exClusions>
<exclusion>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
</exclusion>
</exclusions>
</dependency>

依赖jar包引用,设置自动刷新

使用坐标引入依赖的jar包

  1. 在项目的 pom.xml 中编写 <dependencies> 标签

  2. <dependencies> 标签中 使用 <dependency> 引入坐标

  3. 定义坐标的 groupId,artifactId,version

groupId:定义当前Maven项目隶属的实际项目。

例如org.sonatype.nexus,此id前半部分org.sonatype代表此项目隶属的组织或公司,后部分代表项目的名称。

如果此项目多模块话开发的话就子模块可以分为org.sonatype.nexus.plugins和org.sonatype.nexus.utils等。特别注意的是groupId不应该对应项目隶属的组织或公司,也就是说groupId不能只有org.sonatype而没有nexus。

artifactId:构件ID。该元素定义实际项目中的一个Maven项目或者是子模块,如上面官方约定中所说,构建名称必须小写字母,没有其他的特殊字符,推荐使用“实际项目名称-模块名称”的方式定义,例如:spirng-mvn、spring-core等。

快捷方式引入jar包

  1. 在 pom.xml 中 按 alt + insert,选择 Dependency
  2. 在弹出的面板中搜索对应坐标,然后双击选中对应坐标
  3. 点击刷新按钮,使坐标生效

插件

  • 插件与生命周期内的阶段绑定,在执行到对应生命周期时执行对应的插件功能。
  • 默认maven在各个生命周期上绑定有预设的功能。
  • 通过插件可以自定义其他功能。

示例:Tomcat部署的插件

1
2
3
4
5
6
7
8
9
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
</plugin>
</plugins>
</build>