Maven 简介与快速入门

简要理解

Maven 是为 Java 项目构建管理、依赖管理的工具,可以自动化构建、测试、打包和发布项目,大大提高了开发效率和质量。

主要作用

  • 依赖管理:Maven 可以管理项目的依赖,包括自动下载所需依赖库、自动下载依赖需要的依赖并且保证版本没有冲突、依赖版本管理等。通过 Maven,我们可以方便地维护项目所依赖的外部库,而我们仅仅需要编写配置即可。
  • 构建管理:项目构建是指将源代码、配置文件、资源文件等转化为能够运行或部署的应用程序或库的过程。Maven 可以管理项目的编译、测试、打包、部署等构建过程。通过实现标准的构建生命周期,Maven 可以确保每一个构建过程都遵循同样的规则和最佳实践。同时,Maven 的插件机制也使得开发者可以对构建过程进行扩展和定制。主动触发构建,只需要简单的命令操作即可。

安装与配置

  1. 安装

    软件结构:

    img

  2. 环境变量

    环境变量:配置maven_home 和 path

    img

    img

  3. 命令测试

1
2
mvn -v 
# 输出版本信息,如果此处错误,检查java_home变量
  1. 配置文件

    我们需要需改maven/conf/settings.xml配置文件,来修改maven的一些默认配置。

    主要修改三个配置:

    1.依赖本地缓存位置(本地仓库位置)

    2.maven下载镜像

    3.maven选用编译项目的jdk版本

1
2
3
4
5
6
7
8
<!-- localRepository
| The path to the local repository maven will use to store artifacts.
|
| Default: ${user.home}/.m2/repository
<localRepository>/path/to/local/repo</localRepository>
-->
<!-- conf/settings.xml 55行 -->
<localRepository>D:\repository</localRepository>
1
2
3
4
5
6
7
<!--在mirrors节点(标签)下添加中央仓库镜像 160行附近-->
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
1
2
3
4
5
6
7
8
9
10
11
12
13
<!--在profiles节点(标签)下添加jdk编译版本 268行附近-->
<profile>
<id>jdk-17</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>17</jdk>
</activation>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<maven.compiler.compilerVersion>17</maven.compiler.compilerVersion>
</properties>
</profile>
  1. idea配置本地maven

    将配置好的maven软件配置到idea开发工具中

    1. 打开idea配置文件,构建工具配置

      依次点击

      file / settings / build / build tool / maven

    2. 选中本地maven软件img

    3. 测试是否配置成功

      img

GAVP属性

Maven 中的 GAVP 是指 GroupId、ArtifactId、Version、Packaging 等四个属性的缩写,其中前三个是必要的,而 Packaging 属性为可选项。这四个属性主要为每个项目在maven仓库总做一个标识,方便maven软件对项目进行管理和互相引用。

GAV遵循以下规则:

  • GroupID 格式

    com.{公司/BU }.业务线.[子业务线],最多 4 级。

  • ArtifactID 格式

产品线名-模块名。语义不重复不遗漏。

  • Version版本号格式

    主版本号.次版本号.修订号 1.0.0

    主版本号:当做了不兼容的 API 修改,或者增加了能改变产品方向的新功能。

    次版本号:当做了向下兼容的功能性新增(新增类、接口等)。

    修订号:修复 bug,没有修改方法签名的功能加强,保持 API 兼容性。

  • Packaging定义规则:

    指示将项目打包为什么类型的文件,idea根据packaging值,识别maven项目类型

    packaging 属性为 jar(默认值),代表普通的Java工程,打包以后是.jar结尾的文件。

    packaging 属性为 war,代表Java的web工程,打包以后.war结尾的文件。

    packaging 属性为 pom,代表不会打包,用来做继承的父工程。

1
2
3
4
<modelVersion>4.0.0</modelVersion>
<groupId>com.companyname.project-group</groupId>
<artifactId>project</artifactId>
<version>1.0.0</version>

结构说明

  • pom.xml:Maven 项目管理文件,用于描述项目的依赖和构建配置等信息。
  • src/main/java:存放项目的 Java 源代码。
  • src/main/resources:存放项目的资源文件,如配置文件、静态资源等。
  • src/main/webapp/WEB-INF:存放 Web 应用的配置文件。
  • src/main/webapp/index.html:Web 应用的入口页面。
  • src/test/java:存放项目的测试代码。
  • src/test/resources:存放测试相关的资源文件,如测试配置文件等。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|-- pom.xml                               # Maven 项目管理文件 
|-- src
|-- main # 项目主要代码
| |-- java # Java 源代码目录
| | `-- com/example/myapp # 开发者代码主目录
| | |-- controller # 存放 Controller 层代码的目录
| | |-- service # 存放 Service 层代码的目录
| | |-- dao # 存放 DAO 层代码的目录
| | `-- model # 存放数据模型的目录
| |-- resources # 资源目录,存放配置文件、静态资源等
| | |-- log4j.properties # 日志配置文件
| | |-- spring-mybatis.xml # Spring Mybatis 配置文件
| | `-- static # 存放静态资源的目录
| | |-- css # 存放 CSS 文件的目录
| | |-- js # 存放 JavaScript 文件的目录
| | `-- images # 存放图片资源的目录
| `-- webapp # 存放 WEB 相关配置和资源
| |-- WEB-INF # 存放 WEB 应用配置文件
| | |-- web.xml # Web 应用的部署描述文件
| | `-- classes # 存放编译后的 class 文件
| `-- index.html # Web 应用入口页面
`-- test # 项目测试代码
|-- java # 单元测试目录
`-- resources # 测试资源目录

Maven 核心功能

依赖管理

其实就是定义pom.xml文件而已。

Maven 就能够自动解析项目的依赖关系,并通过 Maven 仓库自动下载和管理依赖,从而避免了手动下载和管理依赖的繁琐工作和可能引发的版本冲突问题。

maven项目信息属性配置和读取:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!-- 模型版本 -->
<modelVersion>4.0.0</modelVersion>

<!-- 公司或者组织的唯一标志,并且配置时生成的路径也是由此生成
如com.Qing.test
maven会将该项目打成的jar包放本地路径:/com/Qing/test -->
<groupId> com.Qing.test </groupId>

<!-- 项目的唯一ID,一个groupId下面可能多个项目,就是靠artifactId来区分的 -->
<artifactId>projectX</artifactId>

<!-- 版本号 -->
<version>1.0.0</version>

<!--打包方式
默认:jar
jar指的是普通的java项目打包方式! 项目打成jar包。
war指的是web项目打包方式!项目打成war包。
pom指这个项目作为父工程,被其他工程聚合或者继承,不打包。
-->
<packaging>jar/pom/war</packaging>

依赖管理和添加:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!-- 
通过编写依赖jar包的gav必要属性,引入第三方依赖。
scope属性是可选的,可以指定依赖生效范围,用得少。
生效范围
- compile :main目录 test目录 打包打包 [默认]
- provided:main目录 test目录 Servlet
- runtime: 打包运行 MySQL
- test: test目录 junit

依赖信息查询方式:
1. maven仓库信息官网 https://mvnrepository.com/ 用得极少
2. mavensearch插件搜索 主要方式
-->
<dependencies>

<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>

<scope>runtime</scope>
</dependency>

</dependencies>

依赖版本提取和维护:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!--声明版本-->
<properties>
<junit.version>4.11</junit.version>
<!-- 也可以通过 maven规定的固定的key,配置maven的参数!如下配置编码格式 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<!--引用properties声明版本,弱耦合 -->
<version>${junit.version}</version>
</dependency>
</dependencies>

依赖传递

依赖传递指的是当一个模块或库 A 依赖于另一个模块或库 B,而 B 又依赖于模块或库 C,那么 A 会间接依赖于 C。

这种依赖传递结构可以形成一个依赖树。当我们引入一个库或框架时,Maven会自动解析和加载其所有的直接和间接依赖,确保这些依赖都可用。

依赖传递的作用是:

  1. 减少重复依赖:当多个项目依赖同一个库时,Maven 可以自动下载并且只下载一次该库。这样可以减少项目的构建时间和磁盘空间。
  2. 自动管理依赖: Maven 可以自动管理依赖项,使用依赖传递,简化了依赖项的管理,使项目构建更加可靠和一致。
  3. 确保依赖版本正确性:通过依赖传递的依赖,之间都不会存在版本兼容性问题,确实依赖的版本正确性.

依赖传递演示:

项目中,需要导入jackson相关的依赖,通过之前导入经验,jackson需要导入三个依赖,分别为:

img

通过查看网站介绍的依赖传递特性:data-bind中,依赖其他两个依赖

img

直接导入data-bind,就可以自动依赖传递需要的依赖

1
2
3
4
5
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.0</version>
</dependency>

A依赖B,B依赖C,导入A就可以自动实现其余的间接依赖。

简单来说,就是导入最底层的依赖即可。

依赖冲突

当直接引用或者间接引用出现了相同的jar包! 这时呢,一个项目就会出现相同的重复jar包,这就算作冲突!依赖冲突避免出现重复依赖,并且终止依赖传递!

img

解决依赖冲突(如何选择重复依赖)方式:

  • 短路优先原则(第一原则)

    A—>B—>C—>D—>E—>X(version 0.0.1)

    A—>F—>X(version 0.0.2)

    则A依赖于X(version 0.0.2)。

  • 依赖路径长度相同情况下,则“先声明优先”(第二原则)

    A—>E—>X(version 0.0.1)

    A—>F—>X(version 0.0.2)

    中,先声明的,路径相同,会优先选择!

构建管理

项目构建是指将源代码、依赖库和资源文件等转换成可执行或可部署的应用程序的过程,在这个过程中包括编译源代码、链接依赖库、打包和部署等多个步骤。

img

主动触发的情况:

  • 重新编译 : 编译不充分, 部分文件没有被编译!
  • 打包 : 独立部署到外部服务器软件,打包部署
  • 部署本地或者私服仓库 : maven工程加入到本地或者私服仓库,供其他工程使用

命令方式构建:

语法: mvn 构建命令 构建命令….

命令 描述
mvn clean 清理编译或打包后的项目结构,删除target文件夹
mvn compile 编译项目,生成target文件
mvn test 执行测试源码 (测试)
mvn site 生成一个项目依赖信息的展示页面
mvn package 打包项目,生成war / jar 文件
mvn install 打包后上传到maven本地仓库(本地部署)
mvn deploy 只打包,上传到maven私服仓库(私服部署)

构建命令周期:

构建生命周期可以理解成是一组固定构建命令的有序集合,触发周期后的命令,会自动触发周期前的命令!也是一种简化构建的思路!

  • 清理周期:主要是对项目编译生成文件进行清理

    包含命令:clean

  • 默认周期:定义了真正构件时所需要执行的所有步骤,它是生命周期中最核心的部分

    包含命令:compile - test - package - install / deploy

  • 报告周期

    包含命令:site

    打包: mvn clean package 本地仓库: mvn clean install

一般使用方案:

1
2
3
打包: mvn clean package
重新编译: mvn clean compile
本地部署: mvn clean install

继承和聚合特性

继承关系

继承是指在Maven项目里,一个项目从另一个项目里直接继承配置信息的机制。有助于简化配置信息,方便管理和维护。

img

一般应用场景:

  • 对一个大型的项目进行了模块拆分。
  • 一个 project 下面,创建了很多个 module。
  • 每一个 module 都需要配置自己的依赖信息。

需求:

  • 多个模块要使用同一个框架,它们应该是同一个版本,所以整个项目中使用的框架版本需要统一管理。
  • 使用框架时所需要的 jar 包组合(或者说依赖信息组合)需要经过长期摸索和反复调试,最终确定一个可用组合。这个方案不应该在新的项目中重新摸索。

通过在父工程中为整个项目维护依赖信息的组合保证了整个项目使用规范、准确的 jar 包,节约时间和精力。

继承语法:

  • 父工程
1
2
3
4
5
6
<groupId>com.Qing.maven</groupId>
<artifactId>maven-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 作为父工程,打包方式必须是 pom -->
<packaging>pom</packaging>

- 子工程
1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- 使用parent标签指定当前工程的父工程 -->
<parent>
<!-- 父工程的坐标 -->
<groupId>com.Qing.maven</groupId>
<artifactId>maven-parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>

<!-- 子工程的坐标 -->
<!-- 如果子工程坐标中的groupId和version与父工程一致,那么可以省略 -->
<!-- <groupId>com.atguigu.maven</groupId> -->
<artifactId>maven-module</artifactId>
<!-- <version>1.0-SNAPSHOT</version> -->

依赖统一管理:

  • 父工程声明版本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<!-- 使用dependencyManagement标签配置对依赖的管理 -->
<!-- 被管理的依赖并没有引入到工程,这里是声明 -->
<dependencyManagement>
<dependencies>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>

</dependencies>
</dependencyManagement>
- 子工程引用版本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!-- 子工程引用父工程中的依赖信息时,写版本号就以自己的为准  -->
<!-- 否则由父工程的dependencyManagement来决定。 -->
<dependencies>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</dependency>

</dependencies>

聚合关系

聚合是指在将多个项目组织到一个父级项目里,触发父工程的构建,统一触发子工程的构建。

聚合作用:

  • 统一管理子项目构建,将多个子项目组织在一起,方便管理和维护。

  • 优化构建顺序,对多个项目进行顺序控制,避免出现构建依赖混乱导致构建失败的情况。

1
2
3
4
5
6
7
8
9
10
11
12
<project>
<groupId>com.Qing</groupId>
<artifactId>parent-project</artifactId>
<packaging>pom</packaging>
<version>1.0.0</version>

<modules>
<module>child-project1</module>
<module>child-project2</module>
</modules>

</project>