Maven 是一个基于 Java 的项目管理和构建自动化工具,广泛用于管理 Java 项目的构建、依赖和发布过程。它通过一套标准化的项目结构和流程,简化了开发人员管理项目的复杂性。
我们来讲一个事例,如果你要构建一个 Java 项目,最简单的方式就是创建一个文件夹,然后创建一个java源文件,编译打包后就可以跑起来了。这时候你发现你需要一个新功能,这个新功能别人已经写好了,你直接使用就可以,于是你上网把别人的 jar 包下载了下来,然后放到你的项目文件夹。这个时候你突然发现,你下载下来的 jar 包,里面还依赖了其他的 jar,你又得去网上找,然后放到自己的项目,于是陷入循环了,你得不停的找包了…
怎么办?maven 来了
Maven 背景
Maven 由 Jason van Zyl 于 2002 年创建,最初是 Apache Turbine 的一个子项目。2003 年,Maven 被接受为 Apache 软件基金会的顶级项目。
Maven 的诞生源于开发人员在项目管理中遇到的以下几个问题:
- 依赖管理复杂:在开发过程中,项目通常需要依赖第三方库,手动管理这些库及其版本关系极易出错,且依赖库之间可能还有复杂的嵌套依赖。
- 构建流程混乱:不同项目可能使用不同的构建工具和流程,导致团队间的协作困难。
- 重复劳动:手动编译代码、运行测试、打包发布不仅耗时,还容易出现人为错误。
Maven 是为了解决这些问题而设计的,它通过统一的构建工具和标准化的项目结构,简化了构建和依赖管理过程。
快速实践
1. 安装 Maven
# Maven 依赖于 Java 环境,因此首先需要确保已经安装 JDK(建议安装 JDK 8 或更高版本)。
# 所以先安装 Java 环境 【这里就不介绍了】
# 安装完成后,使用 java -version 命令确认 Java 是否安装正确。
# 安装 Maven
下载 Maven:Maven 官方下载页面 [https://maven.apache.org/]
解压下载的文件,并将 bin 目录路径添加到系统环境变量 PATH 中。
打开终端/命令行,输入 mvn -v,查看 Maven 是否安装成功。
检测安装结果
mvn –v
mvn –version
2. 快速创建 Maven 项目
# 使用 Maven 创建项目
1. 打开命令行,进入你希望创建项目的目录。
2. 执行以下命令快速生成一个 Maven 项目:
这将创建一个标准的 Maven 项目,groupId 和 artifactId 可以自定义。
mvn archetype:generate -DgroupId=com.example -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
# 项目结构
my-app
├── pom.xml
└── src
├── main
│ └── java
└── test
└── java
pom.xml 是 Maven 项目的核心配置文件,包含项目依赖、版本信息等。
src/main/java 目录放置源代码。
src/test/java 目录放置测试代码。
3. 配置依赖
打开 pom.xml,添加项目需要的依赖。例如,你可以在标签内添加常用库,Maven 会自动下载依赖库并添加到项目中。
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
4. 编译和运行项目
# 执行以下命令编译项目
mvn compile
# 运行测试
mvn test
# 打包项目
mvn package
打包成功后,可以在 target/ 目录下找到生成的 JAR 文件。
Maven 详解
Maven 的项目结构
Maven 项目遵循一种标准的目录结构,旨在为开发人员提供一致的组织方式,使得项目的管理、构建和依赖处理更加便捷。典型的 Maven 项目结构如下:
my-app
├── pom.xml
└── src
├── main
│ ├── java
│ ├── resources
│ └── webapp (可选,用于 Web 应用)
└── test
├── java
└── resources
# 说明
1.根目录 (my-app)
pom.xml: 根目录包含项目的主要配置文件 pom.xml。这是 Maven 项目的核心文件,定义了项目的元数据、依赖、构建配置等。
2. 该目录包含项目的所有源文件和资源文件 (src/)
src/main/java/: 这是存放应用程序 Java 源代码的目录。Java 源文件应按照包结构放置。
src/main/resources/: 用于存放应用程序需要的资源文件,如配置文件、静态资源(XML、YAML、图片等)。这些资源在构建时会被打包到类路径中,供应用程序使用。
src/main/webapp/: 用于 Web 应用项目。包含 Web 资源如 HTML、CSS、JS 文件和 JSP 页面。Maven 会将该目录的内容打包进 WAR 文件。
src/test/java/: 存放单元测试的 Java 代码,通常使用 JUnit 或其他测试框架。测试代码的包结构与 src/main/java/ 中的源代码相对应。
src/test/resources/: 存放测试时需要用到的资源文件(例如测试数据或配置文件)。
Maven 中的坐标概念
在平面几何中坐标(x,y)可以标识平面中唯一的点,而在立体几何中 (x,y,z)可以标识空间中的一个坐标。Maven 也类似采用了这样的一个概念来标识唯一的包坐标。
# Maven 坐标主要组成
groupId 定义当前Maven项目,【包】
artifactId 定义实际项目中的一个模块【模块】
version 定义当前项目的当前版本【版本】
packaging 定义该项目的打包方式,默认jar,还可以是war、ear等
# groupId:
项目的全球唯一标识符,通常使用全限定的包名区分该项目和其他项目。
并且构建时生成的路径也是由此生成。
举例:一般我们公司或者项目的域名是这样的:www.xxx.com.cn
我们会将 xxx.com.cn 的倒转 [cn.com.xxx](http://cn.com.xxx) 作为 groupId,同时也是我们代码工程目录的结构。
# artifactId
构件的标识符,它和 groupId 一起唯一标识一个构件。
换一种说法:groupId 如果理解成一家公司或者项目。artifactId 就想是这家公司下的某个子公司或者子项目。
构件是项目产生的或使用的一个东西,Maven为项目产生的构件包括:JARs,源 码,二进制发布和WARs等。
# version
项目当前版本,格式为:主版本.次版本.增量版本-限定版本号
[**版本种类集合以及常用版本**]
(https://www.notion.so/4cd54c6efbe143388f1afdbfd7c0f18e?pvs=21)
# packaging
项目产生的构件类型,例如jar、war、ear、pom。
插件可以创建他们自己的构件类型,所以前面列的不是全部构件类型
# description
项目的详细描述, Maven 产生的文档用
########## Maven为什么使用坐标?##########
Maven世界拥有大量构建,我们需要找一个用来唯一标识一个构建的统一规范,拥有了统一规范,就可以把查找工作交给机器,默认查找jar包,也就是说在其他项目中依赖它时,能找到它。
举例: 以下是一个 spring-jdbc 的包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.1.RELEASE</version>
</dependency>
Maven 中配置文件 pom.xml
pom.xml 是 Maven 项目的核心配置文件,它定义了项目的基本信息、依赖关系、构建配置、插件等内容。Maven 会根据 pom.xml 里的配置文件自动化管理项目构建流程,包括依赖解析、编译、测试、打包等。
可以说 pom.xml 是 Maven 中最重要的配置文件。上面我们定义了项目的坐标,同时如果我们需要引入其他项目的坐标都是通过这个配置文件。还有管理项目的整个生命周期也是这个文件。
官方说明:maven.apache.org/pom.html
典型的 pom.xml 文件示例
<!-- 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">
<!-- pom模型版本,描述这个pom文件是遵循哪个版本 -->
<modelVersion>4.0.0</modelVersion>
<!-- 自身项目的坐标配置 -->
<groupId>com.example</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<!-- 自身项目名称和描述 -->
<name>My Application</name>
<description>A simple Maven project</description>
<!-- 定义项目中使用的属性,类似定义变量 -->
<!-- 用于设置项目中的全局属性,这些属性可以在 pom.xml 中其他地方引用。例如,<maven.compiler.source> 和 <maven.compiler.target> 定义了编译时使用的 Java 版本 -->
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<!-- 定义项目的依赖项 -->
<dependencies>
<!-- 这个节点定义了项目依赖的外部库。每个依赖项都用 <dependency> 元素表示,并包含 groupId、artifactId、version 等信息。 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<!-- 配置构建过程: 节点定义了项目构建时的行为,包括插件配置、生成目录等 -->
<build>
<!-- 定义项目构建时使用的插件 -->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Maven 中常用命令
Maven 提供了一系列常用的命令,用于管理项目的构建、依赖、测试、打包等操作。以下是 Maven 中常用的命令和它们的作用
# mvn v
查看版本
# mvn clean
作用:清理项目,删除项目生成的所有编译文件和输出文件。
执行内容:删除 target/ 目录。
使用场景:当需要重新构建项目时,清除旧的构建文件,确保构建过程是干净的。
# mvn compile
作用:编译项目的源代码。
执行内容:将 src/main/java 目录下的源代码编译为 .class 文件,生成到 target/classes 目录中。
使用场景:仅需要编译项目时使用。
# mvn test
作用:编译并执行测试代码。
执行内容:Maven 首先编译 src/test/java 目录下的测试代码,并运行测试用例。需要在 pom.xml 中配置测试框架(如 JUnit 或 TestNG)。
使用场景:运行单元测试和集成测试。
# mvn package
作用:将项目打包成可分发的格式(如 JAR 或 WAR)。
执行内容:Maven 会根据 pom.xml 中的打包配置,将项目编译后的类和资源文件打包成 JAR 或 WAR 文件,存储在 target/ 目录下。
使用场景:项目构建完成后,需要将其打包成一个可分发的格式时。
# mvn install
作用:将打包好的项目安装到本地 Maven 仓库。
执行内容:打包项目后,将其安装到本地仓库(通常在 ~/.m2/repository 中)。这使得其他项目可以依赖这个项目的构建结果。
使用场景:将项目作为库或依赖安装到本地 Maven 仓库,方便其他项目引用。
# mvn clean install
作用:首先清理项目,然后重新编译、测试并安装。
执行内容:先执行 clean,再执行 install。这是一种常见的命令组合,确保从干净的状态下构建项目并安装。
使用场景:需要完全重新构建项目,并将结果安装到本地仓库时。
# mvn dependency:tree
作用:查看项目的依赖树,列出所有依赖项及其传递依赖。
执行内容:输出项目所有直接依赖和传递依赖的层次结构。
使用场景:检查项目的依赖关系,尤其是分析依赖冲突问题时。
# mvn test-compile
作用:编译测试代码。
执行内容:仅编译 src/test/java 下的测试源代码。
使用场景:在运行测试前单独编译测试代码。
# mvn validate
作用:验证项目是否正确,并检查所有必要的项目配置信息是否完整。
执行内容:对 pom.xml 进行验证,确保没有缺失的必要信息。
使用场景:在构建之前检查项目的基本配置和依赖是否正确。
# mvn verify
作用:验证项目是否满足质量标准,运行集成测试。
执行内容:在打包之后,执行集成测试,检查项目是否按预期行为工作。
使用场景:确保项目在打包前通过所有集成测试。
# mvn site
作用:生成项目的站点文档。
执行内容:生成包含项目信息的站点报告,例如项目依赖、插件配置、测试覆盖率等,并输出到 target/site/ 目录中。
使用场景:生成项目文档,便于发布或查看项目的整体信息。
# mvn deploy
作用:将项目部署到远程仓库中。
执行内容:在 install 之后,将打包好的项目发布到配置的远程 Maven 仓库。
使用场景:将项目发布到公司内部或公共的 Maven 仓库中,供其他开发者或项目使用。
# mvn archetype:generate
作用:使用 Maven 原型(archetype)生成一个新的 Maven 项目。
执行内容:根据提供的项目模板(archetype)快速生成一个 Maven 项目骨架。
使用场景:创建新的 Maven 项目时,快速生成标准化的项目结构。
Maven 中的仓库
有没有想过一个问题,你引用的别人的包从哪里来呢?还有如果你自己开发了一个包想给别人使用,那你得把这个包放在哪里呢?别人又怎么知道,怎么获取呢?这就是Maven 仓库。
Maven 仓库是存储项目依赖库、插件以及项目构建结果的地方。Maven 使用仓库来管理项目中的各种依赖(如第三方库、插件等)以及构建后的工件(如 JAR 包、WAR 包等)。它是 Maven 项目构建生命周期中必不可少的部分。
Maven 的仓库分为:本地仓库(Local Repository) 远程仓库(Remote Repository)
远程库又分为:中央仓库(Central Repository)镜像仓库(Mirror Repository)快照仓库(Snapshot Repository)
# 本地仓库(Local Repository)
定义:本地仓库是存储在开发者机器上的 Maven 仓库,通常位于 ~/.m2/repository 目录中。
用途:本地仓库用于缓存从远程仓库下载的依赖包和项目构建后的结果。当 Maven 构建项目时,首先会检查本地仓库中是否已经存在所需的依赖,如果存在则直接使用,否则会从远程仓库下载并存储到本地仓库中。
特点:
• 速度快,不需要每次从远程下载依赖。
• 开发者无需手动管理依赖,Maven 会自动下载并存储。
• 允许离线构建项目,因为本地仓库已经缓存了依赖。
• 路径:默认路径为 ~/.m2/repository,可以通过 Maven 的 settings.xml 配置文件自定义本地仓库的位置。
# 远程仓库(Remote Repository)
定义:远程仓库是位于网络上的公共或私有仓库,存储了大量的依赖库、插件和构建结果。Maven 会从远程仓库下载项目所需的依赖,并缓存到本地仓库中。
常见远程仓库:
Maven Central:Maven 官方提供的公共仓库,地址为 https://repo.maven.apache.org/maven2/。绝大多数常用的开源库都可以从 Maven Central 下载。
其他公共仓库:例如 JCenter、Google 的 Android 仓库等,都是公共可访问的远程仓库。
私有仓库:公司内部或团队维护的私有仓库,用于存储内部的库或定制的构建结果。私有仓库通过类似 Nexus、Artifactory 等工具搭建。
特点:
• 公共远程仓库通常是开源库的主要发布渠道,开发者可以从中下载依赖库。
• 私有远程仓库用于内部项目依赖的管理和共享,提升团队的协作效率。
# 中央仓库(Central Repository)
定义:Maven 中央仓库是 Maven 官方提供的默认远程仓库,包含了大量的常用开源库。Maven 中央仓库是所有 Maven 项目默认配置的远程仓库地址,不需要额外配置。
作用:中央仓库是开发者最常用的依赖来源,开发者可以轻松地通过 Maven 自动下载和管理项目中的开源依赖库。
地址:https://repo.maven.apache.org/maven2/
特点:
• 默认配置的远程仓库,用户可以不做任何设置直接使用。
• 提供了大量常见的开源库和插件,便于快速构建项目。
• 自动化版本控制和更新。
# 镜像仓库(Mirror Repository)
定义:镜像仓库是对中央仓库或其他远程仓库的镜像(副本),通常用于提高下载速度和稳定性。通过配置镜像仓库,开发者可以从较近或访问较快的服务器下载依赖。
特点:
• 通过镜像仓库加速依赖下载,解决访问中央仓库慢的问题。
• 在配置 settings.xml 文件中可以指定镜像仓库。
使用场景:
• 当访问 Maven Central 仓库速度较慢时,可以使用国内的镜像仓库(例如阿里云镜像)。
• 当公司内部需要部署一个高效的远程仓库时,可以搭建自己的中央仓库镜像。
# 快照仓库(Snapshot Repository)
定义:快照仓库用于存储项目的开发版本或不稳定的版本,这些版本被称为 “快照”(Snapshot)。快照版本代表的是处于开发过程中的动态版本,而非最终发布的稳定版本。
特点:
• 快照版本是不断更新的,Maven 会每次从远程仓库下载最新的快照版本。
• 快照版本通常用于开发和测试阶段,直到项目进入稳定状态并发布为正式版本。
使用场景:
• 项目处于活跃开发过程中,需要持续集成和测试的版本。
• 快速迭代和试验阶段,发布不稳定的开发版本供团队使用。
Maven 仓库的工作机制
- 搜索依赖:Maven 构建项目时,会首先在本地仓库中查找所需的依赖。如果找不到,则会去远程仓库搜索。
- 下载依赖:如果 Maven 在本地仓库中没有找到依赖,它会从远程仓库下载依赖并存储在本地仓库中。
- 使用依赖:依赖下载并存储后,Maven 会将这些库加入到项目的构建路径中,以便编译、测试和打包时使用。
仓库配置 「官网配置文件说明:maven.apache.org/settings.ht…
仓库的配置主要通过 settings.xml 文件进行。settings.xml 通常位于 ~/.m2/ 目录中,也可以在 Maven 项目中的 pom.xml 文件中配置特定仓库。
<!-- 本地仓库。该值表示构建系统本地仓库的路径。 其默认值为${user.home}/.m2/repository。 -->
<localRepository>/Users/wushiwei/.m2/repository</localRepository>
<!-- Maven是否需要和用户交互以获得输入。如果Maven需要和用户交互以获得输入,则设置成true,反之则应为false。默认为true。 -->
<interactiveMode>true</interactiveMode>
<proxies>
<!--代理元素包含配置代理时需要的信息 -->
<proxy>
<!--代理的唯一定义符,用来区分不同的代理元素。 -->
<id>myproxy</id>
<!--该代理是否是激活的那个。true则激活代理。当我们声明了一组代理,而某个时候只需要激活一个代理的时候,该元素就可以派上用处。 -->
<active>true</active>
<!--代理的协议。 协议://主机名:端口,分隔成离散的元素以方便配置。 -->
<protocol>http://…</protocol>
<!--代理的主机名。协议://主机名:端口,分隔成离散的元素以方便配置。 -->
<host>proxy.somewhere.com</host>
<!--代理的端口。协议://主机名:端口,分隔成离散的元素以方便配置。 -->
<port>8080</port>
<!--代理的用户名,用户名和密码表示代理服务器认证的登录名和密码。 -->
<username>proxyuser</username>
<!--代理的密码,用户名和密码表示代理服务器认证的登录名和密码。 -->
<password>somepassword</password>
<!--不该被代理的主机名列表。该列表的分隔符由代理服务器指定;例子中使用了竖线分隔符,使用逗号分隔也很常见。 -->
<nonProxyHosts>*.google.com|ibiblio.org</nonProxyHosts>
</proxy>
</proxies>
<!--配置服务端的一些设置。一些设置如安全证书不应该和pom.xml一起分发。这种类型的信息应该存在于构建服务器上的settings.xml文件中。 -->
<servers>
<!--服务器元素包含配置服务器时需要的信息 -->
<server>
<!--这是server的id(注意不是用户登陆的id),该id与distributionManagement中repository元素的id相匹配。 -->
<id>server001</id>
<!--鉴权用户名。鉴权用户名和鉴权密码表示服务器认证所需要的登录名和密码。 -->
<username>my_login</username>
<!--鉴权密码 。鉴权用户名和鉴权密码表示服务器认证所需要的登录名和密码。 -->
<password>my_password</password>
<!--鉴权时使用的私钥位置。和前两个元素类似,私钥位置和私钥密码指定了一个私钥的路径(默认是/home/hudson/.ssh/id_dsa)以及如果需要的话,一个密钥 -->
<!--将来passphrase和password元素可能会被提取到外部,但目前它们必须在settings.xml文件以纯文本的形式声明。 -->
<privateKey>${usr.home}/.ssh/id_dsa</privateKey>
<!--鉴权时使用的私钥密码。 -->
<passphrase>some_passphrase</passphrase>
<!--文件被创建时的权限。如果在部署的时候会创建一个仓库文件或者目录,这时候就可以使用权限(permission)。-->
<!--这两个元素合法的值是一个三位数字,其对应了unix文件系统的权限,如664,或者775。 -->
<filePermissions>664</filePermissions>
<!--目录被创建时的权限。 -->
<directoryPermissions>775</directoryPermissions>
<!--传输层额外的配置项 -->
<configuration></configuration>
</server>
</servers>
<!-- 配置私有仓库和镜像仓库 -->
<mirrors>
<!-- 阿里云 Maven 仓库镜像 -->
<mirror>
<id>alimaven</id>
<mirrorOf>central</mirrorOf>
<name>Aliyun Maven</name>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
</mirrors>
<repositories>
<!-- 配置私有仓库 -->
<repository>
<id>my-private-repo</id>
<url>http://my-company-repo.com/repository/maven-releases</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<!--根据环境参数来调整构建配置的列表。settings.xml中的profile元素是pom.xml中profile元素的裁剪版本。-->
<!--它包含了id,activation, repositories, pluginRepositories和 properties元素。-->
<!--这里的profile元素只包含这五个子元素是因为这里只关心构建系统这个整体(这正是settings.xml文件的角色定位),而非单独的项目对象模型设置。-->
<!--如果一个settings中的profile被激活,它的值会覆盖任何其它定义在POM中或者profile.xml中的带有相同id的profile。 -->
<profiles>
<!--根据环境参数来调整的构件的配置 -->
<profile>
<!--该配置的唯一标识符。 -->
<id>test</id>
<!--自动触发profile的条件逻辑。Activation是profile的开启钥匙。-->
<!--如POM中的profile一样,profile的力量来自于它能够在某些特定的环境中自动使用某些特定的值;这些环境通过activation元素指定。-->
<!--activation元素并不是激活profile的唯一方式。settings.xml文件中的activeProfile元素可以包含profile的id。-->
<!--profile也可以通过在命令行,使用-P标记和逗号分隔的列表来显式的激活(如,-P test)。 -->
<activation>
<!--profile默认是否激活的标识 -->
<activeByDefault>false</activeByDefault>
<!--activation有一个内建的java版本检测,如果检测到jdk版本与期待的一样,profile被激活。 -->
<jdk>1.7</jdk>
<!--当匹配的操作系统属性被检测到,profile被激活。os元素可以定义一些操作系统相关的属性。 -->
<os>
<!--激活profile的操作系统的名字 -->
<name>Windows XP</name>
<!--激活profile的操作系统所属家族(如 'windows') -->
<family>Windows</family>
<!--激活profile的操作系统体系结构 -->
<arch>x86</arch>
<!--激活profile的操作系统版本 -->
<version>5.1.2600</version>
</os>
<!--如果Maven检测到某一个属性(其值可以在POM中通过${名称}引用),其拥有对应的名称和值,Profile就会被激活。-->
<!--如果值字段是空的,那么存在属性名称字段就会激活profile,否则按区分大小写方式匹配属性值字段 -->
<property>
<!--激活profile的属性的名称 -->
<name>mavenVersion</name>
<!--激活profile的属性的值 -->
<value>2.0.3</value>
</property>
<!--提供一个文件名,通过检测该文件的存在或不存在来激活profile。missing检查文件是否存在,如果不存在则激活profile。-->
<!--另一方面,exists则会检查文件是否存在,如果存在则激活profile。 -->
<file>
<!--如果指定的文件存在,则激活profile。 -->
<exists>/usr/local/hudson/hudson-home/jobs/maven-guide-zh-to-production/workspace/</exists>
<!--如果指定的文件不存在,则激活profile。 -->
<missing>/usr/local/hudson/hudson-home/jobs/maven-guide-zh-to-production/workspace/</missing>
</file>
</activation>
<!--对应profile的扩展属性列表。Maven属性和Ant中的属性一样,可以用来存放一些值。这些值可以在POM中的任何地方使用标记${X}来使用,这里X是指属性的名称。-->
<!--属性有五种不同的形式,并且都能在settings.xml文件中访问。 -->
<!--1. env.X: 在一个变量前加上"env."的前缀,会返回一个shell环境变量。例如,"env.PATH"指代了$path环境变量(在Windows上是%PATH%)。 -->
<!--2. project.x:指代了POM中对应的元素值。 -->
<!--3. settings.x: 指代了settings.xml中对应元素的值。 -->
<!--4. Java System Properties: 所有可通过java.lang.System.getProperties()访问的属性都能在POM中使用该形式访问, -->
<!-- 如/usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0/jre。 -->
<!--5. x: 在<properties/>元素中,或者外部文件中设置,以${someVar}的形式使用。 -->
<properties>
<!-- 如果这个profile被激活,那么属性${user.install}就可以被访问了 -->
<user.install>usr/local/winner/jobs/maven-guide</user.install>
</properties>
<!--远程仓库列表,它是Maven用来填充构建系统本地仓库所使用的一组远程项目。 -->
<repositories>
<!--包含需要连接到远程仓库的信息 -->
<repository>
<!--远程仓库唯一标识 -->
<id>codehausSnapshots</id>
<!--远程仓库名称 -->
<name>Codehaus Snapshots</name>
<!--如何处理远程仓库里发布版本的下载 -->
<releases>
<!--true或者false表示该仓库是否为下载某种类型构件(发布版,快照版)开启。 -->
<enabled>false</enabled>
<!--该元素指定更新发生的频率。Maven会比较本地POM和远程POM的时间戳。这里的选项是:-->
<!--always(一直),daily(默认,每日),interval:X(这里X是以分钟为单位的时间间隔),或者never(从不)。 -->
<updatePolicy>always</updatePolicy>
<!--当Maven验证构件校验文件失败时该怎么做:-->
<!--ignore(忽略),fail(失败),或者warn(警告)。 -->
<checksumPolicy>warn</checksumPolicy>
</releases>
<!--如何处理远程仓库里快照版本的下载。有了releases和snapshots这两组配置,POM就可以在每个单独的仓库中,为每种类型的构件采取不同的策略。-->
<!--例如,可能有人会决定只为开发目的开启对快照版本下载的支持。参见repositories/repository/releases元素 -->
<snapshots>
<enabled />
<updatePolicy />
<checksumPolicy />
</snapshots>
<!--远程仓库URL,按protocol://hostname/path形式 -->
<url>http://snapshots.maven.codehaus.org/maven2</url>
<!--用于定位和排序构件的仓库布局类型-可以是default(默认)或者legacy(遗留)。-->
<!--Maven 2为其仓库提供了一个默认的布局;然而,Maven 1.x有一种不同的布局。我们可以使用该元素指定布局是default(默认)还是legacy(遗留)。 -->
<layout>default</layout>
</repository>
</repositories>
<!--发现插件的远程仓库列表。仓库是两种主要构件的家。第一种构件被用作其它构件的依赖。这是中央仓库中存储的大部分构件类型。另外一种构件类型是插件。-->
<!--Maven插件是一种特殊类型的构件。由于这个原因,插件仓库独立于其它仓库。pluginRepositories元素的结构和repositories元素的结构类似。-->
<!--每个pluginRepository元素指定一个Maven可以用来寻找新插件的远程地址。 -->
<pluginRepositories>
<!--包含需要连接到远程插件仓库的信息.参见profiles/profile/repositories/repository元素的说明 -->
<pluginRepository>
<releases>
<enabled />
<updatePolicy />
<checksumPolicy />
</releases>
<snapshots>
<enabled />
<updatePolicy />
<checksumPolicy />
</snapshots>
<id />
<name />
<url />
<layout />
</pluginRepository>
</pluginRepositories>
<!--手动激活profiles的列表,按照profile被应用的顺序定义activeProfile。 该元素包含了一组activeProfile元素,每个activeProfile都含有一个profile id。-->
<!--任何在activeProfile中定义的profile id,不论环境设置如何,其对应的 profile都会被激活。-->
<!--如果没有匹配的profile,则什么都不会发生。例如,env-test是一个activeProfile,则在pom.xml(或者profile.xml)中对应id的profile会被激活。-->
<!--如果运行过程中找不到这样一个profile,Maven则会像往常一样运行。 -->
<activeProfiles>
<activeProfile>env-test</activeProfile>
</activeProfiles>
</profile>
</profiles>
Maven 仓库是 Maven 项目构建和依赖管理的核心部分,它通过本地仓库和远程仓库的协同工作,使得依赖的管理变得高效而便捷。开发者通过配置不同类型的仓库,可以根据实际需要来下载依赖、存储构建结果,提升开发和项目管理的效率。
Maven 中的聚合与继承
聚合是指在 Maven 中可以通过一个父项目来管理和构建多个子项目的机制。通过聚合,可以在一个构建命令下同时构建多个子项目。这种方式有助于简化管理多个模块或项目的工作,特别是在需要同时运行多个项目的情况下。
聚合通常是通过在父项目的 pom.xml 文件中使用元素来实现
父项目并不包含实际代码,而是充当容器来管理和构建多个子项目
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>parent-project</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>module1</module>
<module>module2</module>
</modules>
</project>
继承是 Maven 中通过将通用配置(如依赖项、插件等)集中定义在一个父 pom.xml 中,多个子项目可以继承这个父 pom 来共享这些配置。继承的主要目的是减少重复配置,便于统一管理。
子项目通过在 pom.xml 文件中指定父 pom 来实现继承,子项目可以继承父项目中的依赖、插件等配置,并且可以在子项目中进行覆盖或扩展
父项目 pom.xml:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>parent-project</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.9</version>
</dependency>
</dependencies>
</project>
子项目 pom.xml:
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example</groupId>
<artifactId>parent-project</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>child-project</artifactId>
</project>
在这里,子项目 child-project 继承了父项目的所有配置,比如 spring-core 依赖。
Maven 架构设计原理和思想
Maven 架构图示意图
+------------------+
| Core | <-- Maven 核心,负责生命周期和插件管理
+------------------+
|
+------------------+
| Plugin | <-- 各种插件,如编译、测试、打包、部署插件
+------------------+
|
+------------------+
| Repository | <-- 管理依赖库的下载、版本控制、本地缓存
+------------------+
|
+------------------+
| Settings | <-- 配置 Maven 的行为,如代理、仓库路径等
+------------------+
Maven 流程图
+--------------------------+
| 1. 读取 `pom.xml` 文件 |
+--------------------------+
|
+--------------------------+
| 2. 下载依赖并缓存到本地 |
+--------------------------+
|
+--------------------------+
| 3. 执行插件任务(如编译) |
+--------------------------+
|
+--------------------------+
| 4. 打包并生成构建结果 |
+--------------------------+
|
+--------------------------+
| 5. 安装到本地仓库或部署 |
+--------------------------+
Maven 构建项目生命周期图
+-------------------+
| validate | 验证项目是否正确,所有必要信息是否可用
+-------------------+
|
+-------------------+
| compile | 编译项目源代码
+-------------------+
|
+-------------------+
| test-compile | 编译测试代码
+-------------------+
|
+-------------------+
| test | 运行单元测试
+-------------------+
|
+-------------------+
| package | 将编译后的代码打包成可分发的格式(如 JAR、WAR)
+-------------------+
|
+-------------------+
| verify | 运行集成测试,检查打包的有效性
+-------------------+
|
+-------------------+
| install | 将包安装到本地 Maven 仓库
+-------------------+
|
+-------------------+
| deploy | 将最终包复制到远程仓库,供他人共享
+-------------------+
清理(clean)生命周期
+-------------------+
| pre-clean | 执行清理前的预处理步骤
+-------------------+
|
+-------------------+
| clean | 删除之前构建生成的所有文件
+-------------------+
|
+-------------------+
| post-clean | 执行清理后的收尾步骤
+-------------------+
站点(site)生命周期
+-------------------+
| pre-site | 执行生成站点前的预处理
+-------------------+
|
+-------------------+
| site | 生成项目的站点文档
+-------------------+
|
+-------------------+
| post-site | 执行生成站点后的处理
+-------------------+
|
+-------------------+
| site-deploy | 将站点文档部署到远程服务器
+-------------------+
Maven 的三大生命周期它们是相互独立的,可以仅仅调用clean来清理工作目录,仅仅调用site来生成站点,也可以直接运行 mvn clean install site 运行所有这三套生命周期。
补充:Maven 插件管理
Maven 的核心设计只是定义了一套抽象的构建生命周期,Maven 构建执行生命周期时会自动调用相关的插件。Maven 的核心并不直接执行具体的构建任务,而是通过插件来实现这些任务。Maven 的生命周期与插件绑定在一起,每个构建阶段都会触发相应插件的目标(goal)来完成实际的构建操作。
插件可以通过 pom.xml 文件中的节点进行配置。
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
Maven 的架构设计遵循了模块化、插件化和生命周期管理的思想,以实现高效的项目构建和依赖管理。Maven 的设计原理主要围绕以下几个核心思想:
- 声明式构建:通过 pom.xml 文件,开发者只需要声明项目的依赖、插件和目标,Maven 会根据这些声明来自动执行构建任务,无需手动编写复杂的构建脚本。
- 生命周期管理:Maven 定义了一系列的生命周期阶段,开发者可以通过指定执行的生命周期阶段来完成特定的构建任务。
- 插件驱动:Maven 的几乎所有功能都由插件提供,插件可以在不同的生命周期阶段执行不同的任务,如编译、测试、打包等。
- 依赖管理:Maven 通过依赖配置和仓库机制,自动下载、管理和更新项目的依赖库,从而大幅减少了依赖管理的复杂性。
2.3 总结
| 工具 | 优点 | 缺点 | 应用场景 | 特点 |
|---|---|---|---|---|
| Maven | 1. 强大的依赖管理系统2. 预定义生命周期,标准化构建步骤3. 丰富的插件生态 | 1. XML 配置冗长2. 构建速度较慢,尤其是多模块项目 | 适用于依赖复杂、需要稳定构建流程的大型项目 | 采用 XML 配置,构建步骤固定且标准化 |
| Ant | 1. 灵活性高2. 手动控制构建步骤3. 无依赖生命周期,适合定制构建流程 | 1. 没有内置依赖管理系统2. 需要手动编写复杂的构建脚本 | 适用于小型项目或需要高度定制化的构建流程 | 无生命周期概念,适合自定义任务的项目 |
| Gradle | 1. 使用 DSL 语言,配置灵活2. 支持增量构建,构建速度快3. 强大的依赖管理系统 | 1. 学习曲线较陡2. 配置自由度高,复杂项目需更多经验 | 适用于需要快速构建、大规模和复杂依赖的项目 | 使用 Groovy/Kotlin DSL,灵活性强,速度快 |
5 致谢
更多内容欢迎点击阅读原文,喜欢文章的话,也希望能给小编点个赞或者转发,你们的喜欢与支持是小编最大的鼓励,小巫编程室感谢您的关注与支持。好好学习,天天向上(good good study day day up)。
- 官网 官网[1]
- 中央仓库 中央仓库[2]
参考资料
[1] 官网: maven.apache.org/
[2] 中央仓库: maven.apache.org/