maven
概念:Maven就是一个软件,是一款为 Java 项目构建管理、依赖管理的工具(软件)。
作用:使用 Maven 可以自动化构建、测试、打包和发布项目,大大提高了开发效率和质量。
1.1 maven作用理解
1.在实际java项目创建中,往往需要大量的第三方库,如果没有maven,我们需要手动下载这些第三方库的jar包,并copy到项目的lib目录下,过程繁索,如果使用maven,那么我们可以将需要的依赖项的信息编写到Maven工程的配置文件,Maven软件就会自动下载并复制这些依赖项到项目中,也会自动下载依赖需要的依赖!确保依赖版本正确无冲突和依赖完整!(这个功能对应maven的依赖管理功能,这个功能也是maven最核心的功能:Maven 可以管理项目的依赖,包括自动下载所需依赖库、自动下载依赖需要的依赖并且保证版本没有冲突、依赖版本管理等。通过 Maven,我们可以方便地维护项目所依赖的外部库,而我们仅仅需要编写配置即可。)
2.项目开发完成后,想要将项目打成.war文件,并部署到服务器中运行,使用Maven软件,我们可以通过一行构建命令(mvn package)快速项目构建和打包!节省大量时间!(这个对应maven的构建管理功能:
项目构建是指将源代码、配置文件、资源文件等转化为能够运行或部署的应用程序或库的过程!
Maven 可以管理项目的编译、测试、打包、部署等构建过程。通过实现标准的构建生命周期,Maven 可以确保每一个构建过程都遵循同样的规则和最佳实践。同时,Maven 的插件机制也使得开发者可以对构建过程进行扩展和定制。主动触发构建,只需要简单的命令操作即可。
)
1.2 maven工程的gavp属性
Maven工程相对之前的工程,多出一组gavp属性,gav需要我们在创建项目的时指定,p有默认值,后期通过配置文件修改。既然要填写的属性,我们先行了解下这组属性的含义!
Maven 中的 GAVP 是指 GroupId(group组织+id)、ArtifactId(包标示或文件标示)、Version、Packaging 等四个属性的缩写,其中前三个是必要的,而 Packaging 属性为可选项。这四个属性主要为每个项目在maven仓库总做一个标识,类似人的《姓-名》。有了具体标识,方便maven软件对项目进行管理和互相引用!
Packaging定义规则:
指示将项目打包为什么类型的文件,idea根据packaging值,识别maven项目类型!
packaging 属性为 jar(默认值),代表普通的Java工程,打包以后是.jar结尾的文件。
packaging 属性为 war,代表Java的web工程,打包以后.war结尾的文件。
packaging 属性为 pom,代表不会打包,用来做继承的父工程。
1.3 maven核心功能依赖和构建管理
Maven 依赖管理是 Maven 软件中最重要的功能之一。Maven 的依赖管理能够帮助开发人员自动解决软件包依赖问题,使得开发人员能够轻松地将其他开发人员开发的模块或第三方框架集成到自己的应用程序或模块中,避免出现版本冲突和依赖缺失等问题。
我们通过定义 POM 文件,Maven 能够自动解析项目的依赖关系,并通过 Maven **仓库自动**下载和管理依赖,从而避免了手动下载和管理依赖的繁琐工作和可能引发的版本冲突问题。
maven项目信息属性配置和读取:
<!-- 模型版本 -->
<modelVersion>4.0.0</modelVersion>
<!-- 公司或者组织的唯一标志,并且配置时生成的路径也是由此生成, 如com.companyname.project-group,maven会将该项目打成的jar包放本地路径:/com/companyname/project-group -->
<groupId>com.companyname.project-group</groupId>
<!-- 项目的唯一ID,一个groupId下面可能多个项目,就是靠artifactId来区分的 -->
<artifactId>project</artifactId>
<!-- 版本号 -->
<version>1.0.0</version>
<!--打包方式
默认:jar
jar指的是普通的java项目打包方式! 项目打成jar包!
war指的是web项目打包方式!项目打成war包!
pom不会讲项目打包!这个项目作为父工程,被其他工程聚合或者继承!后面会讲解两个概念
-->
<packaging>jar/pom/war</packaging>
依赖管理和添加:
<!--
通过编写依赖jar包的gav必要属性,引入第三方依赖!
scope属性是可选的,可以指定依赖生效范围!
依赖信息查询方式:
1. maven仓库信息官网 https://mvnrepository.com/
2. mavensearch插件搜索
-->
<dependencies>
<!-- 引入具体的依赖包 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
<!--
生效范围
- compile :main目录 test目录 打包打包 [默认]
- provided:main目录 test目录 Servlet
- runtime: 打包运行 MySQL
- test: test目录 junit
-->
<scope>runtime</scope>
</dependency>
</dependencies>
第三方依赖信息怎样知道?(一个dependency就是一个依赖项)
方式一:maven提供的查询官网 https://mvnrepository.com
方式二:maven插件 maven-search
安装插件(安装成功后,重启idea)
在顶部的工具(Tools)中选择maven search
扩展:
1.提取版本号,统一管理。
2.可选属性scope。
scope引入依赖的作用域:
默认:compile 范围:main里+test里+打包和运行里
test 范围:test 测试标签:@test
runtime 范围:mian里不会+test不会+打包和运行的时候会 典型的例子是mysql Class.forName(com.mysql.cj.jdbc.Driver)
provided 范围:main会+test会,但是打包和运行的时候不会包括,典型例子就是 servlet,原因在于tomcat提供了servlet。
依赖版本提取和维护:
<!--声明版本-->
<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>
1.4 依赖传递和冲突
依赖传递指的是当一个模块或库 A 依赖于另一个模块或库 B,而 B 又依赖于模块或库 C,那么 A 会间接依赖于 C。这种依赖传递结构可以形成一个依赖树。当我们引入一个库或框架时,构建工具(如 Maven、Gradle)会自动解析和加载其所有的直接和间接依赖,确保这些依赖都可用。(就是说只需导入B,剩下B会自动去导入C,就是自动导入依赖的依赖)
依赖传递的好处:
1. 减少重复依赖:当多个项目依赖同一个库时,Maven 可以自动下载并且只下载一次该库。这样可以减少项目的构建时间和磁盘空间。
2. 自动管理依赖: Maven 可以自动管理依赖项,使用依赖传递,简化了依赖项的管理,使项目构建更加可靠和一致。
3. 确保依赖版本正确性:通过依赖传递的依赖,之间都不会存在版本兼容性问题,确实依赖的版本正确性!
依赖传递只有在compile dependenices对应的依赖会自动导入(导入依赖,会自动导入依赖的依赖)
依赖冲突(发现已存在依赖(重复依赖)会终止依赖传递,避免循环依赖和重复依赖的问题)。
依赖冲突发生场景:重复依赖
A-------B 1.0(A依赖B1.0)
C-------B 2.0(C依赖B2.0)
如果此时在项目中引入A C,则此时在项目中会引入B的那个版本呢?
依赖冲突的解决原则:
第一原则:谁短谁优先!引入的路径长度。
A -C -B 1.0
F -B 2.0
导入时选择的是A F B 2.0
注意:
A1.1 B2.1 C1.1
F2.2 B2.2
不会引入C1.1 只要发生冲突,后续的依赖传递全部终止。
第二原则:谁上谁优先!dependencies声明的先后顺序(在两者长度相同的情况下,进行第二原则)
当直接引用或者间接引用出现了相同的jar包! 这时呢,一个项目就会出现相同的重复jar包,这就算作冲突!依赖冲突避免出现重复依赖,并且终止依赖传递!
1.5 依赖导入失败的场景以及解决方案
在使用 Maven 构建项目时,可能会发生依赖项下载错误的情况,主要原因有以下几种:
1. 下载依赖时出现网络故障或仓库服务器宕机等原因,导致无法连接至 Maven 仓库,从而无法下载依赖。
2. 依赖项的版本号或配置文件中的版本号错误,或者依赖项没有正确定义,导致 Maven 下载的依赖项与实际需要的不一致,从而引发错误。
3. 本地 Maven 仓库或缓存被污染或损坏,导致 Maven 无法正确地使用现有的依赖项,并且也无法重新下载!
解决方案:
1. 检查网络连接和 Maven 仓库服务器状态。
2. 确保依赖项的版本号与项目对应的版本号匹配,并检查 POM 文件中的依赖项是否正确。
3.清除本地 Maven 仓库缓存(lastUpdated 文件),因为只要存在lastupdated缓存文件,刷新也不会重新下载。本地仓库中,根据依赖的gav属性依次向下查找文件夹,最终删除内部的文件,刷新重新下载即可!(访问本地仓库没有,同时又不访问阿里镜像的问题,说明本地仓库被污染)
脚本使用:
清理maven错误缓存
使用记事本打开 set REPOSITORY_PATH=D:\repository 改成你本地仓库地址即可! 点击运行脚本,即可自动清理本地错误缓存文件!!
1.6 扩展构建管理和插件管理
项目构建是指将源代码、依赖库和资源文件等转换成可执行或可部署的应用程序的过程,在这个过程中包括编译源代码、链接依赖库、打包和部署等多个步骤。
**主动触发场景:**
- 1.重新编译 : 编译不充分, 部分文件没有被编译!
- 2.打包 : 独立部署到外部服务器软件,打包部署
- 3.部署本地或者私服仓库 : maven工程加入到本地或者私服仓库,供其他工程使用
**命令方式构建:**
语法: mvn 构建命令 构建命令....(注意:1.命令构建的时候需要我们进入到项目的根路径 pom.xml平级 2.部署必须是jar包形式,如果是war包,必须放到服务器里,不能部署到本地仓库或者私服仓库。)
命令 描述 mvn clean 清理编译或打包后的项目结构,删除target文件夹(这个文件夹是存储构建后的产物的) mvn compile 编译项目,生成target文件 mvn test 执行测试源码 (测试) mvn site 生成一个项目依赖信息的展示页面 mvn package 打包项目,生成war / jar 文件 mvn install 打包后上传到maven本地仓库(本地部署) mvn deploy 只打包,上传到maven私服仓库(私服部署)
2.通过可视乎方式构建
**构建命令周期:**
构建生命周期可以理解成是一组固定构建命令的有序集合,触发周期后的命令,会自动触发周期前的命令!也是一种简化构建的思路!
- 清理周期:主要是对项目编译生成文件进行清理
包含命令:clean
- 默认周期(构建周期,命令前后顺序固定,执行后面命令时候,会自动执行前面命令,所以写后面命令时候,可以把前面命令省略):定义了真正构件时所需要执行的所有步骤,它是生命周期中最核心的部分
包含命令:compile - test - package - install / deploy
- 报告周期
包含命令:site
打包: mvn clean package 本地仓库: mvn clean install
有序的构建命令容器
清理:clean
构建:compile test package install/deploy
报告:site
因此,打包的时候只需要 mvn package 不需要mvn compile test package(这两个效果一模一样)
最佳方案:
打包: mvn clean package
重新编译: mvn clean compile
本地部署: mvn clean install
补充,如果想要导入自己的插件,可以用以下命令
<!--导入插件--> <build> <plugins> <!--配置插件--> <plugin> </plugin> </plugins> </build>
例如:
<build>
<!-- jdk17 和 war包版本插件不匹配 -->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
</plugins>
</build>
1.7 maven继承关系
1. 继承概念
Maven 继承是指在 Maven 的项目中,让一个项目从另一个项目中继承配置信息的机制。继承可以让我们在多个项目中共享同一配置信息,简化项目的管理和维护工作。
2. 继承作用
作用:在父工程中统一管理项目中的依赖信息,进行统一版本管理!
它的背景是:
- 对一个比较大型的项目进行了模块拆分。
- 一个 project 下面,创建了很多个 module。
- 每一个 module 都需要配置自己的依赖信息。
它背后的需求是:
- 多个模块要使用同一个框架,它们应该是同一个版本,所以整个项目中使用的框架版本需要统一管理。
- 使用框架时所需要的 jar 包组合(或者说依赖信息组合)需要经过长期摸索和反复调试,最终确定一个可用组合。这个耗费很大精力总结出来的方案不应该在新的项目中重新摸索。
通过在父工程中为整个项目维护依赖信息的组合既保证了整个项目使用规范、准确的 jar 包;又能够将以往的经验沉淀下来,节约时间和精力。
3.使用继承时,子工程和父工程的pom应该如何配置
在学习如何配置之前,首先要知道子工程是如何继承父工程的gav属性,其实非常简单,就是在子工程的pom.xml文件中引入<parent>
<!--parent标签就是来指定继承父工程的gav属性--> <parent> <groupId>com.example</groupId> <artifactId>maven-pom-parent-06</artifactId> <version>1.0-SNAPSHOT</version> </parent>
<!--导入依赖,此处导入,所有子工程都有相应的依赖--> <dependencies></dependencies> <!--声明版本信息,声明依赖,但不会下载依赖,可以被子工程继承版本号-->(在父工程使用这个,在子工程进行依赖引入的时候不需要配置版本号,只需要声明ga就行,如果子工程又写了版本,则会覆盖父工程中的依赖) <dependencyManagement> <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.28</version> </dependency> </dependencies> </dependencyManagement>
1.8 maven工程聚合关系
1. 聚合概念 Maven 聚合是指将多个项目组织到一个父级项目中,通过触发父工程的构建,统一按顺序触发子工程构建(构建就是项目开发完成后,想要将项目打成.war文件,并部署到服务器中运行)的过程! 2. 聚合作用 1. 统一管理子项目构建:通过聚合,可以将多个子项目组织在一起,方便管理和维护。 2. 优化构建顺序:通过聚合,可以对多个项目进行顺序控制,避免出现构建依赖混乱导致构建失败的情况。 3. 聚合语法 父项目中包含的子项目列表。 <modules> <module>child-project1</module> <module>child-project2</module> </modules>