Maven简介
Maven是一款为Java项目管理构建、依赖管理的工具,使用Maven可以自动化构建、测试、打包和发布项目,大大提高了开发效率和质量。
Maven可以管理项目的依赖,包括自动下载所需依赖库、自动下载依赖需要的依赖并且保证版本没有冲突、依赖版本管理等。通过Maven,开发人员可以方便地维护项目所依赖的外部库,避免版本冲突和转换错误等,而开发人员仅仅需要编写配置即可。
Maven可以管理项目的编译、测试、打包、部署等构建过程。通过实现标准的构建生命周期,可以确保每一个构建过程都遵循同样的规则和最佳实践。同时,Maven的插件机制也使得开发者可以对构建过程进行扩展和定制,只需要简单的命令操作即可。
Maven安装配置
下载网址:
https://maven.apache.org/download.cgi
注:本文章下载apache-maven-3.9.8-bin.zip,下载后zip文件解压即可。
配置本地仓库地址
修改conf文件夹下settings.xml,增加本地仓库路径(默认路径是${user.home}/.m2/repository)。
<localRepository>D:\maven-repository</localRepository>
配置镜像
修改conf文件夹下settings.xml,配置国内下载镜像。(默认是国外网站,下载较慢,更改为阿里云镜像)。
找到</mirrors>标签,在里面增加以下代码:
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/ </url>
<mirrorOf>central</mirrorOf>
</mirror>
配置JDK版本
修改conf文件夹下settings.xml,配置JDK版本。
找到<profiles>标签,在里面增加以下代码:
<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>
Maven的GAVP
Group ID (G)
Group ID定义了项目所属的组织或组织结构的唯一标识符。它通常是一个反向域名,用于确保唯一性。在Maven中,Group ID有助于区分不同组织或项目组的项目,特别是在依赖管理和仓库查找时非常重要。
Artifact ID(A)
Artifact ID定义了项目在组织内部的唯一标识符。它通常是项目的名称,用来唯一标识一个特定的 Maven项目或模块。
Version(V)
Version定义了项目的当前版本号。版本号遵循语义化版本规范,通常由三部分组成:主版本号、次版本号和修订版本号。Version在Maven中用来唯一标识一个特定版本的项目或模块,以便确定项目的特定发布版本。
Packaging(P)
Packaging定义了项目的打包方式,指定了Maven如何构建项目的输出文件。Maven支持多种打包方式,常见的包括jar(Java应用程序)、war(Web应用程序)、pom(不会打包,用来做继承的父工程)。Packaging是在项目的pom.xml文件中定义的可选元素,默认为jar。
Maven构建命令
mvn clean:用于清理项目,删除target目录及其内容,这些内容通常是在之前的构建过程中生成的临时文件和编译结果。执行这个命令后,会删除旧的构建结果,确保下次构建时从头开始,避免旧的编译结果对新的构建产生影响。
mvn compile:用于编译项目的源代码。它会编译src\main\java目录下的Java源代码,并将编译结果存放在target目录中。
mvn test:用于运行项目的单元测试。它会执行src\test\java目录下的单元测试代码,并输出测试结果。
mvn package:会将编译好的代码打包,生成可分发的jar或war文件(取决于项目类型)。这个命令会执行mvn compile和mvn test,然后将编译好的类文件打包并放置在target目录中。
mvn install:用于将项目的jar或war包安装到本地Maven仓库中。这样其他项目可以通过Maven的依赖管理引用当前项目的构件。通常在多模块项目中,这个命令用来在本地仓库中安装父项目或子项目的构件。
mvn deploy:用于将项目的构件部署到远程Maven仓库,比如公司的私服或者Maven中央仓库。通常用于发布正式版本或者共享项目构件。
mvn site:用于生成项目站点文档的命令。这个命令会执行一系列的文档生成插件,生成项目的站点文档,包括项目的概述、报告、依赖、测试覆盖率等内容。
mvn validate:用于验证项目的正确性和合法性。在Maven构建过程中,各个生命周期阶段都有预定义的目标和插件绑定,validate阶段的作用是在执行实际的构建之前验证项目的状态和配置是否正确。
mvn verify:用于验证项目构建的结果。在Maven的生命周期中,verify阶段是在项目构建之后执行的一个阶段,用于执行各种检查,确保项目的质量和稳定性,通常是在集成测试之后,但在部署阶段之前。
Maven的pom文件
pom.xml文件是Maven中非常重要的配置文件,它使用XML格式来描述项目的信息、依赖项和构建过程,一般有以下部分:
1.根元素。包含了整个 Maven 项目的配置信息。以下是样例:
<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>
<!-- 子元素 -->
</project>
标签说明:xmlns
xmlns:XML命名空间,指定为Maven POM的标准命名空间。
xsi:schemaLocation:用于指定 XML 架构定义(XSD)的位置,确保pom文件可以进行有效的 XML 验证和语法检查。
modelVersion:指定了pom模型的版本,这个版本号告诉Maven如何解析和处理pom.xml文件的内容,如果modelVersion的值不是Maven所支持的版本,Maven构建将会失败。
2.项目基本信息。在pom.xml文件的顶层,通常会包含项目的基本信息。以下是样例:
<!-- 项目基本信息 -->
<groupId>com.example</groupId>
<artifactId>my-project</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>My Project</name>
<description>This is a sample project</description>
标签说明:
groupId:项目组织或公司的唯一标识符,并且配置时生成的路径也是由此生成。
artifactId:项目的唯一标识符,通常与项目文件夹名称相同,一个groupId下面可能多个项目,就是靠artifactId来区分的。
version:项目的版本号。
packaging:打包类型,常见的包括jar、war和pom,默认是jar。
name:项目名称。
description:项目的描述。
3.可重用的属性。用于统一管理和调整项目及各依赖的版本。以下是样例:
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<spring.version>6.1.3</spring.version>
<junit.version>4.13.1</junit.version>
</properties>
标签说明:
maven.compiler.source:标准属性,用于指定项目中Java源代码的版本,按照样例所选择的jdk版本是17。
maven.compiler.target:标准属性,是用来指定生成的 Java 字节码应该兼容的目标 Java 运行时版本,按照样例所选择的jdk版本是17。
spring.version:自定义属性,可随意取名,后续使用时用${spring.version}来指代6.1.3。
junit.version:自定义属性,可随意取名,后续使用时用${junit.version}来指代4.13.1。
4.依赖管理。用于定义项目所依赖的外部库、插件及其版本信息。以下是样例:
<dependencies>
<!-- Spring核心依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- JUnit测试依赖 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
标签说明:
dependency:声明项目的依赖项,指定所需的外部库或者其他Maven项目。
scope:依赖范围,可以设置对应jar包的作用范围。
version:版本,这里的${spring.version}和${junit.version}对应properties标签中设置的值。
注:依赖的信息可以在以下链接搜到:
5.构建配置和插件管理。定义Maven如何构建项目以及管理插件版本。以下是样例:
<build>
<plugins>
<!-- Maven编译器插件配置 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.9.0</version>
<configuration>
<source>17</source> <!-- 源代码编译版本 -->
<target>17</target> <!-- 目标Java版本 -->
</configuration>
</plugin>
<!-- Maven打包插件配置 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.example.App</mainClass> <!-- 主类 -->
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
标签说明:
plugins:插件列表。
plugin:每个插件的声明。
configuration:插件的配置信息。
source:指定了源代码的编译版本。
target:指定了生成的字节码的目标Java版本。
archive:用于配置打包过程中生成的存档。
manifest:元素指定了jar包的MANIFEST.MF文件内容。
addClasspath:表示在MANIFEST.MF中包含类路径信息。
mainClass:指定jar包的主类。
注:编写build元素的内容,需要参考Maven官方文档、各个插件的官方文档或者社区文档。
6.仓库配置。仓库配置部分用于定义项目的依赖仓库。以下是样例:
<!-- 仓库配置 -->
<repositories>
<!-- Maven中央仓库配置 -->
<repository>
<id>alimaven</id>
<url>http://maven.aliyun.com/nexus/content/groups/public/ </url>
</repository>
<!-- 其他仓库配置 -->
</repositories>
标签说明:
repository:定义一个特定的Maven仓库。
id:定义仓库的唯一标识符。
url:定义仓库的URL地址。
注:在大多数情况下,不需要显式地配置仓库,因为Maven会自动从settings.xml文件配置的地址当中下载所需的依赖项。
完整样例如下:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Maven项目的POM文件示例,包含了基本信息、依赖管理、构建配置和插件管理 -->
<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>
<groupId>com.example</groupId> <!-- 项目组织或公司的唯一标识符 -->
<artifactId>my-project</artifactId> <!-- 项目的唯一标识符,通常与项目文件夹名称相同 -->
<version>1.0.0</version> <!-- 项目的版本号 -->
<packaging>jar</packaging> <!-- 打包类型,这里是jar包 -->
<name>My Project</name> <!-- 项目名称 -->
<description>This is a sample Maven project.</description> <!-- 项目描述 -->
<!-- Maven和Java版本 -->
<properties>
<maven.compiler.source>17</maven.compiler.source> <!-- 指定Java源代码版本 -->
<maven.compiler.target>17</maven.compiler.target> <!-- 指定编译后的Java目标版本 -->
<spring.version>6.1.3</spring.version>
<junit.version>4.13.1</junit.version>
</properties>
<!-- 依赖管理 -->
<dependencies>
<!-- Spring核心依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- JUnit测试依赖 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope> <!-- 作用范围为测试 -->
</dependency>
</dependencies>
<!-- 构建配置 -->
<build>
<plugins>
<!-- Maven编译器插件配置 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.9.0</version>
<configuration>
<source>17</source> <!-- 源代码编译版本 -->
<target>17</target> <!-- 目标Java版本 -->
</configuration>
</plugin>
<!-- Maven打包插件配置 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.example.App</mainClass> <!-- 主类 -->
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
<!-- 仓库配置 -->
<repositories>
<!-- Maven中央仓库配置 -->
<repository>
<id>alimaven</id>
<url>http://maven.aliyun.com/nexus/content/groups/public/ </url>
</repository>
<!-- 其他仓库配置 -->
</repositories>
</project>
Maven依赖范围
在pom文件中,scope标签用于定义依赖项的作用范围,即依赖项在项目中的有效性和可见性。通常用于dependency元素内部,用来声明特定依赖项的使用场景和生命周期。
scope标签的常见取值及其含义如下:
1.compile:默认的作用范围,适用于大多数依赖项。当scope标签设置为compile时,依赖项将在编译、测试、运行三个阶段中都有效。这意味着依赖项将被包含在项目中,并且在编译、测试和运行时都可用。
2.provided:依赖项在编译和测试阶段有效,但在打包阶段(如war或者jar文件的打包)时由容器或者 JDK 提供,因此不会包含在最终的部署包中。这通常用于Servlet API、Java EE标准库等,这些库在运行时由容器提供,不需要打包在项目中。
3.runtime:依赖项在编译阶段无效,但在运行和测试时有效。这种依赖项通常用于运行时需要但不是编译时需要的库。
4.test:依赖项仅在测试编译和运行测试时有效,不会包含在项目的正式编译输出或最终部署中。这些依赖项通常是测试框架、测试工具或者辅助测试的库。
5.import:导入依赖范围,该依赖范围只能与dependencyManagement元素配合使用,其功能是将目标pom文件中dependencyManagement的配置导入合并到当前pom的 dependencyManagement中。
6.system:依赖项在编译、测试和运行时都有效,但不会从 Maven 仓库中获取,而是从本地系统路径中获取。这种情况一般很少用到,因为不推荐依赖于系统特定的路径。
Maven依赖传递
Maven 的依赖传递是指在项目中通过Maven管理依赖时,Maven自动处理和解析依赖关系的过程,自动的从 Maven 仓库中下载相应的依赖库。这种传递性能够确保项目依赖的库和插件可以正确地被获取、管理和使用,而无需手动处理每个依赖项的所有依赖关系。
Maven会递归地获取和管理被声明依赖项的所有传递性依赖,形成依赖树,如果项目A依赖于项目B,而项目B又依赖于项目C和项目D,Maven将会自动解析和管理项目C和D的依赖。这种传递性确保了整个依赖链能够被满足,使得项目A可以顺利编译和运行。
当两个或多个依赖项声明了相同的库但不同版本时,就会出现依赖冲突的问题,如:项目A依赖于库X版本 1.0,项目B依赖于库X版本2.0。
在这种情况下,Maven需要解决哪个版本的库X应该被包含在最终构建中。Maven解决依赖冲突的方式有两种,一种是最短路径优先,Maven会选择依赖树中距离项目最近的库版本。这意味着,如果项目A依赖于库X版本1.0,而项目B依赖于库X版本2.0,那么Maven会选择版本2.0,因为它离项目B更近。第二种是声明顺序,两个依赖项声明在pom文件中的顺序不同,Maven会选择第一个声明的版本。
也可以使用exclusions标签,在引用其他项目时,手动排除依赖。以下是样例:
<dependency>
<groupId>com.example</groupId>
<artifactId>my-project</artifactId>
<version>1.0.0</version>
<scope>compile</scope>
<!-- 使用excludes标签配置依赖的排除 -->
<exclusions>
<!-- 在exclude标签中配置一个具体的排除 -->
<exclusion>
<!-- 指定要排除的依赖的坐标(不需要写版本) -->
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
或者使用optional标签在被传递的项目上,指定依赖不可进行传递。以下是样例:
<dependency>
<groupId>com.example</groupId>
<artifactId>my-project</artifactId>
<version>1.0.0</version>
<!-- 使用optional标签,说明该依赖不可传递 -->
<optional>true</optional>
</dependency>
maven继承
Maven继承是指在Maven的项目中,让一个项目从另一个项目中继承配置信息的机制。继承可以让在多个项目中共享同一配置信息,简化项目的管理和维护工作。
一般父工程使用dependencyManagement标签来管理依赖,而子工程选择继承父工程的依赖。
父工程配置样例:
<groupId>com.example</groupId>
<artifactId>parent-project</artifactId>
<version>1.0.0</version>
<!-- 当前工程作为父工程,它要去管理子工程,所以打包方式必须是pom -->
<packaging>pom</packaging>
<!-- 使用dependencyManagement标签配置对依赖的管理 -->
<!-- 被管理的依赖并没有真正被引入到工程 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>6.1.3</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
子项目是直接继承自父项目的项目模块。子项目通过parent标签来声明它的父项目。
<parent>
<groupId>com.example</groupId>
<artifactId>parent-project</artifactId>
<version>1.0.0</version>
</parent>
<!-- 如果子工程坐标中的groupId和version与父工程一致,那么可以省略 -->
<!-- <groupId>com.example</groupId> -->
<artifactId>child-project1</artifactId>
<!-- <version>1.0.0</version> -->
<!-- 子工程引用父工程中的依赖信息时,可以把版本号去掉。 -->
<!-- 把版本号去掉就表示子工程中这个依赖的版本由父工程的dependencyManagement来决定。 -->
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
</dependencies>
maven聚合
在Maven中,聚合是一种组织多个相关项目的方法,允许将多个单独的Maven项目作为一个大的项目来管理和构建。Maven 聚合是指将多个项目组织到一个父级项目中,以便一起构建和管理的机制。聚合可以更好地管理一组相关的子项目,同时简化它们的构建和部署过程,还可以对多个项目进行顺序控制,避免出现构建依赖混乱导致构建失败的情况。
聚合配置是在父亲工程的pom文件配置的,使用modules标签进行管理,以下是样例:
<groupId>com.example</groupId>
<artifactId>parent-project</artifactId>
<version>1.0.0</version>
<!-- 当前工程作为父工程,它要去管理子工程,所以打包方式必须是pom -->
<packaging>pom</packaging>
<!-- module标签的内容是文件的路径 -->
<modules>
<module>child-project1</module>
<module>child-project2</module>
<module>../child-project3</module>
<module>../../child-project4</module>
</modules>