Maven是一个Java项目管理和构建工具,他可以定义项目结构、项目依赖,并使用同意的方式进行自动化构建,是Java项目中不可缺少的工具。
了解maven本质上就是了解pom.xml文件夹
一般我们在生成一个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">
<!--版本相关-->
<modelVersion>4.0.0</modelVersion>
<!--本项目坐标信息(每个maven项目都会有唯一的坐标)-->
<!--通过这这三项组成的,通过坐标信息可以定位到具体的Jar包信息-->
<!--定位过程是仓库->镜像->找不到报错not found-->
<groupId>com.ztt</groupId> <!-- groupId 组织名称,一般是域名反写-->
<artifactId>untitled</artifactId> <!-- artifactId 项目名-->
<version>1.0-SNAPSHOT</version> <!-- version 版本名称-->
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
本质上就是:如何通过坐标信息引用jar包
maven项目在<dependencies></dependencies>
引入依赖(引入jar包)。
在pom.xml添加servlet的依赖
<dependencies>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
</dependencies>
pom.xml属性管理一般用<properties> </properties>
包裹。
如下所示,同时下面我也介绍了几个常用的属性配置。
<!--属性变量-->
<properties>
<!--JDK版本-->
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<!--编码-->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!--这里也经常用于声明依赖的版本-->
<javax.servlet.version>3.1.0</javax.servlet.version>
</properties>
注意properties
中经常用于生命依赖的版本,这样做的好处是可以帮助我们进行统一的版本管理。
具体操作如下。
IDEA中打开Maven控制界面,查看生命周期
依赖作用范围一般在<scope></scope>
中设置
Maven的依赖范围包括:编译、测试、运行\打包(刚入门可以把运行和打包理解成一个)
编译:只在main\java的中有效
测试:只在main\test中有效
运行\打包:项目生成war、jar包时,在运行过程中使用到该依赖。
在Maven中,依赖可以传递的,假设存在三个项目,项目A、项目B、项目C。假设C依赖B,B依赖A,那么我们可以根据Maven项目依赖的特征推断出项目C也依赖项目A。
依赖冲突通常发生在项目中使用了多个库,而这些库又依赖于相同库的不同版本时。这种情况可能导致构建失败或运行时错误,因为Java运行时环境要求所有类库的版本必须一致。下面是一个具体的例子来说明依赖冲突:
假设你正在开发一个Java Web应用程序,并且你的项目有以下依赖关系:
你的项目直接依赖于LibraryA,版本1.0。
LibraryA又依赖于CommonLib,版本1.5。
同时,你的项目还直接依赖于LibraryB,版本2.0。
而LibraryB也依赖于CommonLib,但需要版本2.0。
这里的依赖关系可以表示为:
在这个例子中,CommonLib的两个不同版本(1.5和2.0)被引入到项目中,这将导致依赖冲突。Maven会尝试根据其依赖解析策略来解决这个冲突,但如果没有明确指定版本,可能会导致以下问题:
Maven的依赖调解原则,通常被称为"最近依赖者优先"或"第一声明者原则"(First Declaration Rule),是Maven处理传递性依赖冲突时使用的一种策略。这个原则确保了依赖冲突可以通过一个简单的规则来解决,从而避免了复杂的版本冲突问题。
第一声明者原则的工作原理:
依赖树的构建:Maven首先构建项目的依赖树,包括直接依赖和所有间接依赖。
冲突检测:在构建依赖树的过程中,Maven会检测到多个依赖项可能依赖于同一个库的不同版本。
选择依赖版本:当检测到版本冲突时,Maven会选择依赖树中距离项目最近的依赖项指定的版本。换句话说,它会选择第一个声明该库依赖的依赖项的版本。
忽略后续声明:在依赖树中,任何后续声明的相同库的不同版本将被忽略,即使它们可能是更新的或更低的版本。
路径近者优先原则(Shortest Path Rule)是Maven处理依赖冲突时使用的另一种策略,它与第一声明者原则有相似之处,但更侧重于依赖路径的长度。这个原则确保了在多个依赖项指向同一个库的不同版本时,Maven选择路径最短的依赖版本。
路径近者优先原则的工作原理:
依赖树构建:Maven构建项目的依赖树,包括直接依赖和间接依赖。
冲突检测:在构建依赖树的过程中,Maven检测到多个依赖项可能依赖于同一个库的不同版本。
最短路径选择:当检测到版本冲突时,Maven会选择依赖路径最短的依赖项指定的版本。依赖路径是指从项目到依赖项的直接距离。
忽略长路径声明:即使长路径上的依赖项声明了更新或更低的版本,Maven也会忽略它,因为根据路径近者优先原则,它不是最优选择。
依赖排除是Maven处理依赖冲突的一种常用方法。以下是如何进行依赖排除的一个具体例子:
假设你的项目直接依赖于两个库:LibraryA 和 LibraryB。但是,LibraryA 和 LibraryB 都间接依赖于同一个库 CommonLib,并且它们依赖的 CommonLib 版本不同。为了解决这个冲突,你可以选择排除一个版本的 CommonLib,并显式地声明你需要的版本作为直接依赖。
以下是pom.xml文件中的依赖配置示例:
<dependencies>
<!-- 直接依赖LibraryA -->
<dependency>
<groupId>com.example</groupId>
<artifactId>LibraryA</artifactId>
<version>1.0</version>
<!-- 排除LibraryA中对CommonLib 1.5的依赖 -->
<exclusions>
<exclusion>
<groupId>com.common</groupId>
<artifactId>CommonLib</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 直接依赖LibraryB -->
<dependency>
<groupId>com.example</groupId>
<artifactId>LibraryB</artifactId>
<version>2.0</version>
<!-- 排除LibraryB中对CommonLib 2.0的依赖 -->
<exclusions>
<exclusion>
<groupId>com.common</groupId>
<artifactId>CommonLib</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 显式声明CommonLib的版本,确保使用一致的版本 -->
<dependency>
<groupId>com.common</groupId>
<artifactId>CommonLib</artifactId>
<version>1.5</version> <!-- 假设我们决定使用1.5版本 -->
</dependency>
</dependencies>
<!-- ... 其他配置 ... -->
在这个例子中,我们首先排除了 LibraryA 和 LibraryB 中对 CommonLib 的依赖。然后,我们添加了一个直接依赖项,指定了 CommonLib 的版本为1.5。这样,无论 LibraryA 和 LibraryB 依赖的是 CommonLib 的哪个版本,Maven都会使用我们显式声明的版本1.5。
通过这种方式,你可以控制项目中使用的依赖项的版本,避免由于依赖传递带来的版本冲突问题。
Maven聚合项目(也称为多模块项目或父项目)是一种项目组织方式,它允许你将一个大项目分解成多个小的、可管理的模块。每个模块可以独立构建和维护,同时仍然可以作为一个整体来构建和分发。
对于项目开发,聚合项目有以下好处
模块化:将一个大项目分解成多个模块,有助于更好地组织代码,每个模块负责特定的功能或组件。
重用性:模块化使得代码可以在不同项目中重用,因为它们可以作为独立的组件进行构建和部署。
并行开发:在多模块项目中,不同的团队可以同时在不同的模块上工作,这有助于提高开发效率和加快开发速度。
依赖管理:父项目可以使用部分来统一管理所有子模块的依赖版本,确保依赖的一致性。
作为聚合项目,其父项目应该
<packaging></packaging>
一般为jar或者war,但是作为父项目,其不是一个具体的包,固其中pom.xml中的应进行<packaging>pom</packaging>
设置。<modules> </modules>
管理子工程因篇幅问题不能全部显示,请点此查看更多更全内容