Maven 的介绍
Maven 是 Java 项目管理和构建的工具,它可以:
- 定义项目结构
- 管理项目依赖
- 使用统一的方式进行自动化构建
是 Java 项目不可缺少的工具。
标准化的项目结构有助于程序的复现
不同的开发工具所创建的项目结构是不同的,而使用 Mavem 统一了项目结构,能增强项目的可阅读性,以及降低项目入手的门槛
规整的项目依赖好过复杂的 jar 包导入
Maven 工具会帮我们管理所有的 jar 包
传统的、不使用 Maven 的项目
- jar 包与项目强绑定,必须要放置在项目文件夹中,如果项目 jar 包很多的情况下,占用磁盘空间会非常大
- 团队协作开发时,每一个开发人员都需要下载对应的 jar 包文件
- 传输项目时间长(因为项目大)
Maven 引入了“仓库”的概念
- 仓库中放置了所有的 jar 包,需要的 jar 包会以依赖的方式从网络上下载并导入程序
- 团队协作开发时,只需要将代码传输即可,jar 包会被 Maven 以依赖的形式自动导入
自动化的构建流程减少不必要的额外操作
Maven 提供了一套标准化的构建流程,它封装了一系列功能,对外暴露接口以供调用,那些复杂且无太大意义的过程被它隐藏了
编辑
Maven 的下载和安装
Maven 下载
Maven 官网: Download Apache Maven – Maven
编辑
系统 Maven 环境配置
环境的配置和 JDK 环境配置是一样的了,自行进行配置即可
编辑
Maven 基本配置
Maven 安装完成后在 apache-maven*/conf/settings.xml 文件中配置对应的基本信息。
当你第一次执行 mvn 相关的命令时,Maven 会自动在家目录中创建 .m2 文件夹,里面会放置全局的配置
接下来的基本配置可以在 .m2/settings.xml 中进行配置
Maven Jar 包安装路径配置
在下方可以增加 jar 包安装路径相关的配置,默认是放置在 .m2 文件夹中
编辑
Maven 仓库配置
在文件中可以增加中央仓库的配置,当依赖查找时会自上而下查找仓库中是否有对应的依赖
编辑
Maven 脚手架结构
使用 Maven 构造工具创建项目
如下图所示,可以使用构造工具创建对应的项目
编辑
脚手架内容结构
Maven 是基于约定的方式进行项目构建和管理的,比如下图中基础的脚手架结构,创建后会产生多个文件。(其中 .idea 和 .gitignore 分别是 IDEA 和 Git 自动生成的文件)
编辑
Maven 提供的自动打包工具
在 IDEA 的右侧菜单栏中可以使用 maven 自动打包工具,其中所有的操作都是顺序执行的,比如要使用 package 则前面的所有过程会被自动执行一遍
编辑
Maven 项目中 pom.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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<!-- maven 版本相关信息 -->
<modelVersion>4.0.0</modelVersion>
<!--
设置打包方式,可以打成以下 3 中包的形式
* jar: 依赖注入的需求,如果使用 war 则无法作为依赖注入其他项目(默认打包方式)
* war: Tomcat 运行 Web 项目需要使用 war 包的形式
* pom: 若是多模块项目,父模块不进行打包则使用 pom
-->
<packaging>jar</packaging>
<!-- 坐标信息:可以通过下面三个变量确定 jar 包在仓库中的位置 -->
<!-- groupId 一般使用域名反写 如: com.baidu -->
<groupId>com.sereneDream</groupId>
<!-- artifacId 一般使用项目名称 如: mavenTest -->
<artifactId>mavenTest</artifactId>
<!-- 为当前模块/项目的版本 -->
<version>1.0-SNAPSHOT</version>
<!-- 属性、变量可以在这里声明,随后在下方的依赖中直接引用。方便管理依赖版本 -->
<properties>
<!-- 当前项目的 JDK 版本 -->
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<!-- 当前项目的编码形式 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- 同样的,可以创造变量,比如我拥有一个 hutool 依赖,我可以在 properties 中声明变量,并在下面使用 -->
<cn.hutool.version>5.8.37</cn.hutool.version><!-- 内容对应与 47 行的 hutool 依赖的版本 -->
</properties>
<!--
依赖和 jar 包的区别:
* 一个依赖中可能包含多个 jar 包
* 依赖可以说是 maven 的专业名词
所以在 Maven 项目中都是说:“引入一个‘依赖’”
-->
<!--
dependencies 标明可以引入多个依赖
- maven 在使用时,会现在本地仓库中查找依赖信息,
如果本地仓库中没有对应的依赖信息,则回去远程仓库中查找
- 在刚开始使用时,本地是没有对应的依赖信息缓存的,
所以需要去依赖仓库直接获取对应的依赖信息
依赖仓库地址: https://mvnrepository.com/
-->
<dependencies>
<!-- 使用 <dependency> 标签的方式引入依赖 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${cn.hutool.version}</version><!-- 对应了 25 行的变量 -->
<!-- 内容可替换为 <version>5.8.37</version> -->
<!--
依赖范围: 这个依赖在项目进行哪一项操作时会被使用,哪一项操作不会被使用
范围种类(依赖能够在哪里使用/出现):
* 编译(main/java)
* 测试(main/test)
* 运行/打包(能够出现在包内的依赖)
依赖范围 范围种类 示例依赖
compile 编译✔️ 测试✔️ 打包✔️ 默认依赖范围
provided 编译✔️ 测试✔️ 打包✖️ servlet 这类 tomcat 服务器中已经依赖的 jar 包
runtime 编译✖️ 测试✔️ 打包✔️ 数据库驱动 这类使用反射获取的 jar 包
test 编译✖️ 测试✔️ 打包✖️ junit 测试相关的依赖
system 编译✔️ 测试✔️ 打包✖️ 不会依赖仓库中的 jar 包,而是使用本地仓库中的 jar 包,
通常会与 <systemPath>本地仓库 jar 包地址</systemPath> 一起使用
-->
<scope>compile</scope>
</dependency>
</dependencies>
</project>
依赖传递
简单而言就是如果你依赖了一个 jar 包中存在另一个你需要依赖的 jar 包,则视为你已依赖改 jar 包
比如:A 项目依赖了 B 项目, B 项目依赖了 hutool
根据依赖传递的特性,A 项目也会存在 hutool 依赖
当然,父项目也可以选择不去向子项目传递对应的依赖,可以使用 true 阻止依赖传递
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<groupId>com.sereneDream</groupId>
<artifactId>mavenTest</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<cn.hutool.version>5.8.40</cn.hutool.version>
</properties>
<dependencies>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${cn.hutool.version}</version>
<!-- 当父模块设置 optional 为 true 时,标明这个依赖不进行传递 -->
<optional>true</optional>
</dependency>
</dependencies>
</project>
依赖的排除和覆盖
如果父模块不允许修改的情况下,子模块也可以通过 exclusion 标签对父模块的部分依赖进行忽略
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<groupId>com.sereneDream</groupId>
<artifactId>mavenTest</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<cn.hutool.version>5.8.40</cn.hutool.version>
<spring-boot-starter-web.version>2.7.0</spring-boot-starter-web.version>
</properties>
<dependencies>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${cn.hutool.version}</version>
</dependency>
<!--
这里我使用 spring-boot-starter-web 依赖进行 <依赖的排除和覆盖> 的示例,
这个依赖会传递引入:
- spring-webmvc(Spring MVC 框架)
- spring-boot-starter-tomcat(内嵌 Tomcat 服务器)
- spring-boot-starter-json(JSON 处理)
- spring-boot-starter(Spring Boot 核心)
- spring-core(Spring 核心)
- ... 总共约 10-15 个依赖
-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring-boot-starter-web.version}</version>
<!--
在 spring-boot-starter-web 依赖中,
我们如果不想要使用其传递引入的依赖,可以使用 exclusions 标签对依赖进行排除
同样的,一个 exclusions 中包含多个 exclusion
-->
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 如果仅仅只是版本不符合项目所需,也可以使用覆盖的方式去覆盖父依赖引入的依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>4.0.2</version>
</dependency>
</dependencies>
</project>
Maven 聚合项目
一个 Maven 项目可以多模块,也就是聚合项目,如下图(mavenTest 的打包要设置为 pom)
编辑
在父模块中需要标明所有的子模块信息,这样子,当父模块点击打包时会同时将子模块的项目进行打包
如下图,我父模块仅仅声明了 a 为子模块,打包后,仅仅只有 a 模块进行了打包,b 模块没有任何活动
编辑
Maven 继承
在聚合的同时,子模块可以继承与父模块的依赖,即需要在子模块中添加父模块信息,如下图
父模块中引入了 hutool 依赖,子模块 a 开启了依赖,并标明了父模块信息,子模块 b 反之,从右侧的模块依赖信息可知:a 已经成功依赖 hutool,而 b 没有任何依赖
编辑