04-Maven-第 4 章 项目构建:生命周期与插件
04-Maven-第 4 章 项目构建:生命周期与插件
ProriseMaven-第 4 章 项目构建:生命周期与插件
摘要: 在上一章,我们掌握了如何管理项目的“原材料”——依赖。本章,我们将学习如何将这些原材料加工成最终产品。我们将深入 Maven 的第二个核心能力:项目构建。您将学习到什么是 生命周期,它如何为所有 Java 项目提供一套标准化的构建流程,并最终理解到,所有实际工作都是由其背边的“工匠”——插件——来完成的。
4.1. 构建生命周期:Maven 的标准化流程
[生命周期(Lifecycle)是 Maven 中最具创新性的概念之一。它不是一个具体的程序,而是一套抽象的、标准化的项目构建流程规范。理解了生命周期,就理解了 Maven 自动化构建的精髓。]
4.1.1. 什么是生命周期?
我们可以将 Maven 的生命周期想象成一条“软件生产流水线”。这条流水线被预先定义好了,包含了一系列固定的、有序的“工位”,这些工位在 Maven 中被称为 阶段 (Phase)。
例如,一条典型的生产线可能包含“编译”、“测试”、“打包”等工位。无论我们要生产什么产品(项目),都必须依次经过这些工位。这种标准化的流程,确保了所有产出(无论是您自己还是团队其他成员构建的项目)都遵循同样的规范,具有同样的高品质。
4.1.2. Maven 的三大生命周期
Maven 内置了三条完全独立的生命周期(流水线),它们各自负责不同的任务,互不干扰。
🧹 clean 生命周期:清理工作区
这条流水线的任务非常专一:打扫战场。
它的主要目标是删除上一次构建时生成的所有文件,最典型的就是删除整个 target 目录,确保我们能在一个干净的环境下进行全新的构建。
它包含以下核心阶段:
pre-clean: 执行清理前需要完成的工作。clean: (核心) 删除上一次构建生成的所有文件。post-clean: 执行清理后需要完成的工作。
⚙️ default 生命周期:核心生产线
这是 最重要、最核心 的一条流水线,定义了项目从源代码到最终产物的完整构建过程。
我们日常绝大部分的 Maven 操作都与它相关。
它的核心阶段非常多,常见的如:
validatecompiletestpackageverifyinstalldeploy
我们将在下一节中对这些阶段进行详细介绍。
📄 site 生命周期:报告生成线
这条流水线的任务是为项目生成一个文档站点,包含项目的详细信息、各类测试报告、代码质量分析等。
它的核心阶段包括:
pre-site: 执行站点生成前需要完成的工作。site: (核心) 生成项目站点文档。post-site: 执行站点生成后需要完成的工作。site-deploy: 将生成的站点部署到指定的服务器。
4.1.3. 生命周期核心原则
1. 独立性
三大生命周期是 完全相互相互独立的。调用其中一条生命周期中的任何阶段,都不会对另外两条生命周期产生任何影响。
例如,我们执行 mvn clean 命令,它只会调用 clean 生命周期的 clean 阶段,而不会触及 default 生命周期的任何操作。
这也是为什么我们经常使用 mvn clean install 这样的组合命令。这实际上是 Maven 先后执行了两个独立的指令:首先调用 clean 生命周期的 clean 阶段进行清理,然后调用 default 生命周期的 install 阶段进行构建和安装。
2. 顺序性
在 同一个生命周期内部,所有阶段都是严格有序的。当我们调用一个阶段时,Maven 会自动从该生命周期的起始阶段开始,按顺序执行,直到我们指定的阶段为止。
例如,default 生命周期的顺序是 ... -> compile -> test -> package -> ...。当我们执行 mvn package 命令时,Maven 实际上会依次执行 validate, compile, test, package 等所有在 package 之前(包括 package 自身)的阶段。这个特性极大地简化了我们的操作,我们无需手动按顺序敲入一长串命令。
4.2. 详解 default 生命周期的核心阶段
[现在,我们聚焦于最核心的 default 生命周期,通过一个时间线的形式,来详细观察一个项目是如何从源代码一步步“进化”成最终产物的。]
项目起始
compile
阶段: compile
这是构建过程的第一个重要里程碑。在此阶段,Maven 会调用编译器(如 javac),将我们编写的位于 src/main/java 目录下的所有 .java 源代码文件,编译成 JVM 可以执行的 .class 字节码文件,并输出到 target/classes 目录下。
test
阶段: test
为了保证项目质量,test 阶段会执行所有的单元测试。它首先会编译 src/test/java 目录下的测试代码(test-compile 阶段),然后运行这些测试。如果任何一个单元测试失败,整个构建过程将在此处 立即中止,这是保证项目健康度的重要关卡。
package
阶段: package
当所有代码编译完成并通过测试后,package 阶段会将 target/classes 目录下的 .class 文件、以及 src/main/resources 目录下的配置文件等资源,按照项目的打包类型(由 pom.xml 中的 <packaging> 标签定义),打包成一个单独的可分发文件。
- 如果
<packaging>是jar,则会生成一个.jar文件。 - 如果
<packaging>是war,则会生成一个.war文件。
.jar 主要用于封装可独立运行的 Java 应用程序或库,包含类文件、资源文件等;.war 是 Web 应用程序归档文件,除了包含应用代码和资源,还包含 Web 相关配置,用于部署到 Web 服务器如 Tomcat 等。
这个最终的产物会被放置在 target 目录下。
install
阶段: install
install 阶段不仅仅是打包。它会执行 package 的所有操作,然后额外多做一个非常重要的工作:将 package 阶段生成的项目产物(如 .jar 文件)复制并安装到我们的 “本地仓库” 中。
这么做的好处是,一旦一个项目被 install,我们本机上的其他 Maven 项目就可以在自己的 pom.xml 中像依赖第三方库一样,直接依赖这个项目了。
deploy
阶段: deploy
这是 default 生命周期的最后一个核心阶段。deploy 会执行 install 的所有操作,然后更进一步:将项目产物 上传并部署到“远程仓库”(通常是公司的私服 Nexus)。
一旦项目被 deploy,整个团队的所有成员就都可以通过配置他们的 Maven 来依赖和使用这个项目了,这是团队协作和成果共享的关键步骤。
这个是我们后续的详细讲解的配置相关内容!
4.3. 插件:Maven 的真正执行者
[生命周期和阶段都只是“规范”和“流程图”,它们本身并不能做任何实际的工作。那么,编译、打包这些具体的操作到底是谁完成的呢?答案就是——插件 (Plugin)。]
4.3.1. 插件与生命周期的关系
我们可以这样理解三者的关系:
- 生命周期 (Lifecycle): 定义了项目的 顶级构建流程(如 default)。
- 阶段 (Phase): 构成了生命周期的 有序步骤(如 compile, package)。
- 插件目标 (Plugin Goal): 真正执行任务的“工人”。
Maven 的运行机制,就是将特定的“插件目标”绑定到特定的“生命周期阶段”上。当 Maven 执行到一个阶段时,就会调用所有绑定在该阶段上的插件目标来完成具体工作。
4.3.2. 核心插件与目标(Goal)介绍
下表展示了 default 生命周期中一些核心阶段与其默认绑定的插件和目标:
| Phase | Plugin | Goal | 功能描述 |
|---|---|---|---|
compile | maven-compiler-plugin | compile | 编译 src/main/java 下的源码。 |
test | maven-surefire-plugin | test | 运行 src/test/java 下的单元测试。 |
package | maven-jar-plugin | jar | 将项目打包成 JAR 文件。 |
install | maven-install-plugin | install | 将项目安装到本地仓库。 |
deploy | maven-deploy-plugin | deploy | 将项目部署到远程仓库。 |
4.3.3. 自定义插件配置
虽然 Maven 为各阶段都绑定了功能完善的默认插件,但我们也可以在 pom.xml 的 <build> 标签中对这些插件进行自定义配置,以满足项目的特殊需求。
最常见的场景就是为项目单独指定编译时使用的 JDK 版本,这可以覆盖 settings.xml 中的全局配置,保证项目在任何环境下都使用我们期望的 JDK 版本进行编译,极大地增强了项目的可移植性。
1 | <build> |
<source> 标签指定了要使用的 Java 源码版本,<target> 标签指定编译生成的字节码目标版本,按配置编译出的代码就对应相应版本特性,
现在执行 mvn compile 命令时,就可以打包指定的 Java 版本了
4.4. 高频面试题
Q: 请说一下 mvn clean, compile, package, install 这几个命令有什么区别和联系?
A: 这是一个非常经典的 Maven 面试题,我们可以从以下四个方面来回答:
1. 功能区别
mvn compile: 只执行 default 生命周期到 compile 阶段。它的作用是将主程序代码(src/main/java)编译成.class文件,输出到target/classes目录。mvn package: 执行 default 生命周期到 package 阶段。它会先完成 compile 和 test 的所有工作,然后将项目打包成一个.jar或.war文件,存放在target目录下。mvn install: 执行 default 生命周期到 install 阶段。它会先完成 package 的所有工作,然后把最终的包文件安装到我们的 本地仓库 中。mvn clean: 执行 clean 生命周期的 clean 阶段。它的功能非常纯粹,就是删除整个target目录,清理之前构建的所有产物。
2. 从属关系
- compile, package, install 三者都属于 default 生命周期。
- clean 属于 clean 生命周期。
3. 递进关系
- 在 default 生命周期中,三者是严格的递进关系:install 包含了 package 的所有功能,package 包含了 compile 的所有功能。
- clean 与 default 生命周期的任何阶段都是 完全独立 的。
4. 使用场景
mvn compile: 只想检查代码是否有编译错误时使用。mvn package: 当我们需要得到项目的可执行/可部署包(如.jar文件)时使用。这是最常用的打包命令。mvn install: 当我们本地的另一个项目需要依赖此项目时使用。通过 install,我们将此项目变成了可被其他项目依赖的“本地库”。mvn clean install或mvn clean package: 这是最推荐的组合命令。通过先 clean,可以确保我们是在一个完全干净的环境下进行全新的打包或安装,避免了旧的编译文件可能带来的干扰。





