Maven 构建生命周期

Maven 构建生命周期定义了一个项目构建跟发布的过程,包含三种标准生命周期:

  • clean:清理项目
  • default(或 build):核心构建流程
  • site:生成项目文档
img

每个生命周期由多个阶段(phase)组成,执行时按顺序运行,大概流程如下所示

img

Maven 生命周期的本质是 “预定义的阶段序列”,每个阶段对应特定的 “动作”,且阶段之间存在顺序依赖关系(执行后续阶段时,会自动执行所有前置阶段)。

clean 生命周期

clean 生命周期负责清理项目构建时候产生的临时文件和目录(主要是target/),这是它的唯一职责,避免旧文件干扰新构建,确保构建环境 “干净”

clean 生命周期的核心目标:删除项目根目录下的 target/ 文件夹,该文件夹是Maven 默认的构建输出目录,包含编译后的 class 文件、jar/war 包、测试报告等),以及其他临时文件(如 IDE 生成的缓存文件)

clean 生命周期是 Maven 中最简单的生命周期,仅包含 3 个有序阶段,阶段名称和执行顺序固定,且必须按顺序执行,执行后续阶段会自动触发前置阶段。

阶段名称(Phase) 执行顺序 核心作用 是否会删除 target/
pre-clean 1(前置) 清理前的准备工作(如备份旧文件、检查清理权限)
clean 2(核心) 执行核心清理逻辑(默认删除 target/ 目录) 是(核心动作)
post-clean 3(后置) 清理后的收尾工作(如删除 IDE 缓存、清理日志文件) 否(可选扩展)

Maven 生命周期的 “阶段” 本身只是 “抽象步骤”,需要通过绑定插件的目标(Goal) 来实现具体功能。clean 生命周期的阶段默认绑定了 Maven 官方插件 maven-clean-plugin,无需额外配置即可使用。

只执行 clean 之后代码大部分都会报错,类似于部分 IDE(如 IntelliJ)依赖 target/ 中的编译文件,clean 后可能提示 “类找不到”。一般重新编译项目(如 mvn compile 或 IDE 中的 “Rebuild Project”)即可恢复。

在父模块根目录执行 mvn clean,会递归清理所有子模块的 target/ 目录,无需逐个模块执行。

首先是 pre-clean 阶段

默认行为:无任何绑定插件,即默认不执行任何操作(空阶段)。

扩展场景:若需在清理前做准备(如备份 target/ 中的旧 jar 包),可手动绑定自定义插件目标。

示例:清理前备份 target/libbackup/ 目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<!-- 绑定到 pre-clean 阶段 -->
<phase>pre-clean</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<!-- 执行备份命令 -->
<copy todir="${project.basedir}/backup/lib">
<fileset dir="${project.build.directory}/lib"/>
</copy>
</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
clean 阶段

默认绑定插件maven-clean-plugin:clean(Maven 内置,无需手动配置)。

核心功能:删除 target/ 目录发生在这个阶段

插件可配置项:通过 maven-clean-plugin 可扩展清理范围(如删除额外目录 / 文件),常见配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<version>3.3.2</version>
<configuration>
<!-- 1. 强制删除只读文件(如某些 IDE 锁定的缓存文件) -->
<force>true</force>
<!-- 2. 额外删除的目录(除了 target/ 外,再删除 logs/ 和 temp/) -->
<dirs>
<dir>${project.basedir}/logs</dir>
<dir>${project.basedir}/temp</dir>
</dirs>
<!-- 3. 额外删除的文件(如根目录的 test.txt) -->
<files>
<file>${project.basedir}/test.txt</file>
</files>
<!-- 4. 清理前打印详细日志(调试时常用) -->
<verbose>true</verbose>
</configuration>
</plugin>
</plugins>
</build>
post-clean 阶段

默认行为:无任何绑定插件,即默认不执行任何操作(空阶段)。

扩展场景:清理后的收尾工作,如删除 IDE 生成的 .idea/(IntelliJ)或 .settings/(Eclipse)目录、清理系统临时文件等。

示例:清理后删除 IntelliJ 的缓存目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<phase>post-clean</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<!-- 删除 .idea/ 目录 -->
<delete dir="${project.basedir}/.idea"/>
</target>
</configuration>
</execution>
</executions>
</plugin>

default 生命周期

default 生命周期是 Maven 最主要的生命周期,用于处理项目的构建、测试、打包、部署等核心流程。

一个典型的 Maven 构建(build)生命周期是由以下几个阶段的序列组成的:

阶段 处理 描述
验证 validate 验证项目 验证项目是否正确且所有必须信息是可用的
编译 compile 执行编译 源代码编译在此阶段完成
测试 Test 测试 使用适当的单元测试框架(例如JUnit)运行测试。
包装 package 打包 将编译后的代码打包成可分发的格式,例如 JAR 或 WAR
检查 verify 检查 对集成测试的结果进行检查,以保证质量达标
安装 install 安装 安装打包的项目到本地仓库,以供其他项目使用
部署 deploy 部署 拷贝最终的工程包到远程仓库中,以共享给其他开发人员和工程

为了完成 default 生命周期,这些阶段(包括其他未在上面罗列的生命周期阶段)将被按顺序地执行。

拆分一下,就是这样的

  1. validate
  • 阶段作用:验证项目是否具备执行后续构建操作的必要信息和条件,比如检查项目的 POM 文件是否正确,配置是否完整等。
  • 示例场景:如果 POM 文件中存在语法错误,或者缺少关键的依赖配置信息,在执行到这个阶段时就会报错并停止构建。
  1. initialize
  • 阶段作用:初始化构建状态,例如设置属性值、创建需要的目录等。
  • 示例场景:在构建过程中需要创建一些临时目录用于存放中间文件,这个阶段就会进行相关目录的创建操作。
  1. generate-sources
  • 阶段作用:生成编译时需要的源代码,这些源代码不是手动编写的,而是通过一些工具生成的,比如使用注解处理器生成辅助代码等。
  • 示例场景:在使用某些框架(如 JAXB 用于 XML 绑定)时,可能会通过插件自动生成与 XML 模式对应的 Java 类,这个生成过程就发生在这个阶段。
  1. process-sources
  • 阶段作用:对生成的源代码进行处理,比如过滤、修改等。
  • 示例场景:可以通过配置对生成的源代码中的一些占位符进行替换,或者根据不同的构建环境对代码进行调整。
  1. generate-resources
  • 阶段作用:生成主代码中需要使用的资源文件,例如配置文件等。
  • 示例场景:根据不同的环境(开发、测试、生产)生成不同配置内容的 application.properties 文件。
  1. process-resources
  • 阶段作用:复制和处理主资源文件到目标目录,准备打包。例如对资源文件进行过滤,替换其中的占位符等操作。
  • 示例场景:如果资源文件中有一些需要根据环境动态替换的变量(如数据库连接地址),可以在这个阶段进行替换操作,然后将处理后的文件复制到 target/classes 目录中。
  1. compile
  • 阶段作用:编译项目的主源代码,将 Java 源文件(通常在 src/main/java 目录下)编译成字节码文件(.class 文件),输出到 target/classes 目录。
  • 示例场景:日常开发中执行 mvn compile 命令,就是执行这个阶段,用于快速编译代码,检查语法错误等。
  1. process-classes
  • 阶段作用:对编译后的类文件进行进一步的处理,比如字节码增强等操作,不过在常规项目中较少使用。
  • 示例场景:在一些需要对字节码进行动态修改和增强的场景(如使用 AspectJ 进行面向切面编程时对字节码织入切面逻辑),可能会用到这个阶段。
  1. generate-test-sources
  • 阶段作用:生成测试代码编译时需要的源代码,和 generate-sources 类似,不过针对的是测试代码。
  • 示例场景:如果项目中使用了一些测试框架(如 JUnit 5 的动态测试功能),可能会通过插件生成相关的测试辅助代码。
  1. process-test-sources
  • 阶段作用:对生成的测试源代码进行处理,类似于 process-sources,但针对测试代码。
  • 示例场景:对测试代码中使用的配置文件等资源进行过滤和处理,以适应测试环境。
  1. generate-test-resources
  • 阶段作用:生成测试时需要使用的资源文件,比如测试配置文件等。
  • 示例场景:生成用于单元测试的模拟数据库配置文件,或者测试用的示例数据文件。
  1. process-test-resources
  • 阶段作用:复制和处理测试资源文件到测试目标目录,通常是 target/test-classes 目录。
  • 示例场景:将测试配置文件中的占位符替换为测试环境的值,然后复制到测试类路径下供测试代码使用。
  1. test-compile
  • 阶段作用:编译项目的测试源代码,将测试 Java 源文件(通常在 src/test/java 目录下)编译成字节码文件,输出到 target/test-classes 目录。
  • 示例场景:当执行 mvn test-compile 命令时,就会执行这个阶段,用于编译测试代码,为后续的测试执行做准备。
  1. process-test-classes
  • 阶段作用:对编译后的测试类文件进行进一步处理,和 process-classes 类似,不过针对测试类文件。
  • 示例场景:在一些复杂的测试场景中,可能需要对测试类的字节码进行增强或修改,以满足特定的测试需求。
  1. test
  • 阶段作用:使用合适的单元测试框架(如 JUnit、TestNG 等)运行测试代码,对项目中的单元测试进行验证,不过不会运行集成测试。
  • 示例场景:执行 mvn test 命令,Maven 会自动发现并运行 src/test/java 目录下符合测试框架约定的测试类,输出测试结果报告。
  1. prepare-package
  • 阶段作用:在真正打包之前,对要打包的内容进行最后的准备工作,例如对已编译的代码和资源进行整理和校验。
  • 示例场景:检查打包所需的文件是否完整,对文件进行一些最后的格式调整等操作。
  1. package
  • 阶段作用:将编译后的代码和资源文件打包成可分发的格式,如 JAR(用于 Java 类库)、WAR(用于 Web 应用)、EAR(用于企业级应用)等。生成的包文件会放在 target 目录下。
  • 示例场景:执行 mvn package 命令,会根据项目的类型(如普通 Java 项目、Web 项目等)生成对应的包文件,方便后续的部署和分发。
  1. pre-integration-test
  • 阶段作用:在运行集成测试之前执行一些准备操作,比如启动外部服务、配置测试环境等。
  • 示例场景:如果项目的集成测试依赖于数据库,在这个阶段可以启动数据库服务,并初始化测试数据。
  1. integration-test
  • 阶段作用:运行项目的集成测试,验证不同模块或系统之间的交互是否正常。
  • 示例场景:通过模拟用户请求,测试 Web 应用中各个服务层、数据访问层之间的协同工作情况,确保整个系统功能的正确性。
  1. post-integration-test
  • 阶段作用:在集成测试完成后执行一些清理和收尾操作,比如停止外部服务、清理测试数据等。
  • 示例场景:关闭在 pre-integration-test 阶段启动的数据库服务,并删除测试过程中产生的临时数据。
  1. verify
  • 阶段作用:验证包是否有效且达到质量标准,比如检查测试结果是否符合预期,包的完整性等。
  • 示例场景:如果单元测试或集成测试中有测试用例失败,在这个阶段 Maven 会认为构建不符合质量标准,构建过程会失败。
  1. install
  • 阶段作用:将打包好的项目安装到本地仓库,供本地其他项目依赖使用。对于 Java 项目,就是将生成的 JAR、WAR 等包安装到本地 Maven 仓库(默认路径为 ~/.m2/repository)。
  • 示例场景:当开发了一个 Java 类库项目,执行 mvn install 后,其他本地项目就可以在 POM 文件中添加依赖,引用这个类库。
  1. deploy
  • 阶段作用:将最终的包发布到远程仓库,供其他开发人员或项目共享和使用。通常在项目发布到生产环境时执行。
  • 示例场景:将开发好的项目发布到公司内部的 Maven 私服(私有仓库),或者发布到公共的 Maven 中央仓库(需要满足一定的条件和流程),方便团队成员或其他开源项目使用。

在实际使用中,可以通过 mvn 命令加上对应的生命周期阶段名称来执行特定阶段及其之前的所有阶段。

存在如下常用命令,常用的真就这些

1
2
3
4
5
mvn compile     # 编译主代码
mvn test # 运行测试
mvn package # 打包(生成target/*.jar)
mvn install # 安装到本地仓库(~/.m2/repository)
mvn deploy # 部署到远程仓库(需配置distributionManagement)

其中,详细的说明一下 install 和 deploy

install 阶段会将项目打包好的构件安装到本地 Maven 仓库,这个仓库就是在 IDEA 中你设置的那个存依赖的地方,也就是 repository 文件夹,一般大家都会通过修改 Maven 的 settings.xml 配置文件来自定义本地仓库的位置,在 settings.xml 中找到 <localRepository> 标签,其值为你期望的路径,忘了就在这找,这个优先级比你在 IDEA 中设置的要更高

那么作用是什么,其实这个你自己执行的比较少,框架自动执行会比较多,本地仓库的存在,方便了同一台机器上多个项目复用构件 。当项目 A 执行 install 后,项目 B 如果在 POM 文件中声明了对项目 A 构件的依赖,Maven 就会优先从本地仓库查找并引入,而无需每次都从远程仓库下载,提升了构建效率。

那么,deploy 阶段会将项目最终的包上传到远程仓库,以便与其他开发人员或工程共享。

这个仓库并不是 Git 那种代码仓库,而是针对于 Maven 的依赖私有仓库,许多公司或团队会搭建自己的 Maven 私服,如使用 Nexus、Artifactory 等工具搭建。私服的地址通常是公司内部的一个特定 URL。开发人员在公司内部进行项目协作时,将构件部署到私服,团队其他成员就可以从私服拉取所需的依赖。

最知名的公共 Maven 仓库是 Maven 中央仓库(Central Repository),其地址是 https://repo.maven.apache.org/maven2/ 。不过,直接向中央仓库部署构件需要经过严格的审核和一系列复杂的流程。此外,还有一些其他的公共仓库,如 Sonatype 的 OSSRH(用于开源项目发布)等。

要让 deploy 阶段正常工作,需要在项目的 POM 文件中配置 <distributionManagement> 标签 ,指定要部署到的远程仓库地址和相关信息。例如,对于发布正式版本到私服的配置示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
<distributionManagement>
<repository>
<id>my-releases</id>
<name>Internal Releases</name>
<url>http://your-company-domain.com/nexus/content/repositories/releases/</url>
</repository>
<snapshotRepository>
<id>my-snapshots</id>
<name>Internal Snapshots</name>
<url>http://your-company-domain.com/nexus/content/repositories/snapshots/</url>
</snapshotRepository>
</distributionManagement>

同时,还需要在 settings.xml 中配置对应的认证信息(用户名和密码等),以确保 Maven 有权限将构件上传到远程仓库:

1
2
3
4
5
6
7
8
9
10
11
12
<servers>
<server>
<id>my-releases</id>
<username>your-username</username>
<password>your-password</password>
</server>
<server>
<id>my-snapshots</id>
<username>your-username</username>
<password>your-password</password>
</server>
</servers>

总的来说,install 主要服务于本地开发环境的构件管理,而 deploy 侧重于项目构件在团队或更广泛范围内的共享和分发。

构建阶段由插件目标构成

在 Maven 中,构建阶段(Phase) 本身并不直接执行具体操作,而是通过插件目标(Plugin Goal) 来完成实际工作。

插件目标(Plugin Goal)是具体的执行单元,代表一个特定的任务(比构建阶段更精细)。每个插件可以包含多个目标,用于完成相关的一组操作。

  • 示例maven-compiler-plugin(编译插件)有两个核心目标:

    • compile:compile:编译主源代码(对应 compile 阶段)
    • compile:testCompile:编译测试源代码(对应 test-compile 阶段)

    又如 maven-surefire-plugin(测试插件)的 surefire:test 目标,负责执行单元测试(对应 test 阶段)。

Maven 的构建阶段(如 compiletestpackage 等)本身只是 “抽象的步骤”,其功能通过绑定插件目标来实现。

  • 默认绑定: Maven 为 defaultcleansite 三大生命周期的阶段预设了插件目标绑定。例如:

    • compile 阶段默认绑定 maven-compiler-plugin:compile 目标;
    • test 阶段默认绑定 maven-surefire-plugin:test 目标;
    • package 阶段默认绑定 maven-jar-plugin:jar 目标(Java 项目)或 maven-war-plugin:war 目标(Web 项目)。
  • 自定义绑定: 你可以在项目 POM 中为任意阶段绑定额外的插件目标,实现个性化需求。例如,将代码检查插件的目标绑定到 compile 阶段,确保每次编译前先检查代码规范:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <build>
    <plugins>
    <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-checkstyle-plugin</artifactId>
    <version>3.2.0</version>
    <executions>
    <!-- 绑定checkstyle:check目标到compile阶段 -->
    <execution>
    <phase>compile</phase>
    <goals>
    <goal>check</goal> <!-- 具体要执行的插件目标 -->
    </goals>
    </execution>
    </executions>
    </plugin>
    </plugins>
    </build>

然后,插件目标的执行有两种常见方式:绑定到阶段执行直接调用执行

当插件目标绑定到某个阶段后,执行该阶段时会自动触发目标。

  • 执行顺序:一个阶段可以绑定多个目标,按 POM 中配置的顺序依次执行。
  • 示例:若 compile 阶段绑定了 checkstyle:checkcompiler:compile 两个目标,则执行 mvn compile 时,会先运行代码检查,再执行编译。

未绑定到任何阶段的目标,可以通过 mvn 插件前缀:目标名 直接调用,无需依赖生命周期。

  • 示例

    mvn help:describe:直接执行 maven-help-plugindescribe 目标,查看插件信息(不涉及任何构建阶段)。

    mvn dependency:tree:直接执行 maven-dependency-plugintree 目标,查看项目依赖树(独立于生命周期)。

当同时指定构建阶段和插件目标时,Maven 会按以下规则确定执行顺序:

  1. 先执行所有阶段及其绑定的目标(按生命周期顺序,如 validatecompiletest);
  2. 再执行直接指定的插件目标(按命令中书写的顺序)。
  • 示例:执行命令mvn clean compile dependency:tree
    1. 先执行 clean 生命周期(删除 target 目录);
    2. 再执行 default 生命周期的 validatecompile 阶段(包括绑定的编译目标);
    3. 最后执行 dependency:tree 目标(打印依赖树)。

所以,一个插件目标代表一个特定的任务(比构建阶段更为精细),这有助于项目的构建和管理。这些目标可能被绑定到多个阶段或者无绑定。不绑定到任何构建阶段的目标可以在构建生命周期之外通过直接调用执行。这些目标的执行顺序取决于调用目标和构建阶段的顺序。

这段从菜鸟教程抄的话是什么意思呢,也就是说了这句话的是 Maven 里的 “插件目标” 和 “构建阶段” 的关系

  1. 插件目标是具体干活的:比如 “编译代码”“运行测试” 这些具体操作,都是由某个插件的目标来完成的,它比 “构建阶段”(比如 compile、test 这些步骤)更具体。
  2. 目标可以灵活绑定:一个目标可以绑定到多个阶段(比如某个个代码检查的目标,既可以在编译前执行,也可以在测试前执行),也可以不绑定任何阶段。
  3. 执行方式灵活
    • 绑定了阶段的目标,会跟着阶段自动执行(比如执行mvn compile时,编译目标会自动跑);
    • 没绑定阶段的目标,需要手动直接调用(比如mvn dependency:tree查看依赖树);
    • 执行顺序由 “阶段的固定顺序” 和 “命令里写的顺序” 共同决定。

例如,考虑下面的命令:

clean 和 pakage 是构建阶段,dependency:copy-dependencies 是目标

1
mvn clean dependency:copy-dependencies package

这里的 clean 阶段将会被首先执行,然后 dependency:copy-dependencies 目标会被执行,最终 package 阶段被执行。

Clean 生命周期

clean是 Maven 三大生命周期之一,专门用于清理项目构建产生的文件,它包含 3 个固定阶段,按顺序执行:

  1. pre-clean:在清理操作前执行的准备工作(如备份需要保留的文件)。
  2. clean:核心清理操作,删除上一次构建生成的所有文件(默认删除target目录)。
  3. post-clean:清理完成后执行的收尾工作(如记录清理日志、通知清理结果)。

和 Maven 其他生命周期一样,clean生命周期遵循 “执行某阶段时,会先执行其之前所有阶段” 的规则,执行 mvn post-clean:会按顺序执行 pre-cleancleanpost-clean(共 3 个阶段)。

无论你指定哪个阶段,Maven 都会从生命周期的第一个阶段开始,逐步执行到你指定的阶段。

Maven 的生命周期阶段本身只是 “步骤标记”,实际操作需要通过插件目标来完成。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<build>
<plugins>
<plugin>
<!-- 使用maven-antrun-plugin插件,它可以执行Ant命令(如echo输出文本) -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.1</version>

<!-- 配置插件的执行规则:绑定到哪些阶段,执行哪些目标 -->
<executions>
<!-- 1. 绑定到pre-clean阶段 -->
<execution>
<id>id.pre-clean</id> <!-- 唯一标识,用于区分多个执行配置 -->
<phase>pre-clean</phase> <!-- 绑定的阶段 -->
<goals>
<goal>run</goal> <!-- 执行插件的run目标(该目标用于运行Ant任务) -->
</goals>
<configuration>
<tasks>
<echo>pre-clean phase</echo> <!-- Ant任务:输出文本 -->
</tasks>
</configuration>
</execution>

<!-- 2. 绑定到clean阶段(同上逻辑) -->
<execution>
<id>id.clean</id>
<phase>clean</phase>
<goals><goal>run</goal></goals>
<configuration>
<tasks><echo>clean phase</echo></tasks>
</configuration>
</execution>

<!-- 3. 绑定到post-clean阶段(同上逻辑) -->
<execution>
<id>id.post-clean</id>
<phase>post-clean</phase>
<goals><goal>run</goal></goals>
<configuration>
<tasks><echo>post-clean phase</echo></tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

上面的示例通过maven-antrun-plugin插件,为clean生命周期的 3 个阶段绑定了具体任务,实现了 “在每个阶段打印文本” 的功能。

Default (Build) 生命周期

上面说了 Build 阶段的主要那些生命周期及其 23 步,但是有一些与 Maven 生命周期相关的重要概念需要说明:

当一个阶段通过 Maven 命令调用时,例如 mvn compile,只有该阶段之前以及包括该阶段在内的所有阶段会被执行,而且不同的 maven 目标将根据打包的类型(JAR / WAR / EAR),不同项目类型对应不同的打包插件:Java 项目默认使用 maven-jar-plugin 生成 JAR,Web 项目使用 maven-war-plugin 生成 WAR。

实际开发中,常用的 Default 生命周期命令及执行的阶段如下:

  • mvn compile:执行 validatecompile(编译主代码)。
  • mvn test:执行 validatetest(编译并运行单元测试)。
  • mvn package:执行 validatepackage(打包构件,如生成 JAR/WAR)。
  • mvn install:执行 validateinstall(打包并安装到本地仓库)。
  • mvn deploy:执行所有 23 个阶段(打包并部署到远程仓库)。

Site 生命周期

Maven 的Site生命周期是专门用于生成和部署项目站点文档的生命周期,它能自动整合项目信息、报告数据等内容,生成美观且规范的 HTML 文档站点,Site 生命周期专注于项目文档的自动化管理,通过整合插件生成包含项目说明、依赖信息、测试报告、代码质量分析等内容的静态站点,并支持将站点部署到服务器供团队共享。

Site生命周期包含 4 个固定阶段,按顺序执行,每个阶段承担特定任务:

  1. pre-site
    • 作用:在生成站点文档前执行准备工作,例如清理旧的站点文件、准备生成文档所需的资源(如自定义模板、logo 图片)、检查文档生成依赖是否齐全等。
    • 示例:若项目站点需要引用外部静态资源(如团队图标),可在该阶段将资源复制到指定目录。
  2. site
    • 作用:生成项目的核心站点文档,是Site生命周期中最核心的阶段。默认会整合pom.xml中的项目信息(如名称、版本、开发者信息),并通过插件生成各类报告(如依赖树、测试覆盖率、代码规范检查结果等)。
    • 生成位置:文档默认输出到target/site目录,包含 HTML、CSS 等静态文件,可直接在浏览器中打开查看。
    • 示例输出:从执行日志可见,该阶段会生成 “项目团队”“依赖信息”“许可证” 等多种报告,这些都是项目文档的重要组成部分。
  3. post-site
    • 作用:在站点文档生成后、部署前执行收尾工作,例如校验生成的文档完整性(如是否所有报告都成功生成)、压缩站点文件以减小体积、生成部署所需的元数据(如站点版本信息)等。
    • 目的:确保站点文档符合部署要求,为后续的site-deploy阶段做准备。
  4. site-deploy
    • 作用:将site阶段生成的站点文档部署到指定的服务器(如公司内部的 Web 服务器、Nexus 私服的站点仓库等),供团队成员或外部人员访问。
    • 配置要求:需在pom.xml<distributionManagement>中配置站点部署地址(如<site><url>http://your-server/site-repo</url></site>),并在settings.xml中配置服务器认证信息。

和 Maven 其他生命周期一样,Site生命周期遵循 “执行某阶段时,自动执行其之前所有阶段” 的规则

我们一般通过配置更多插件(如maven-javadoc-plugin生成 API 文档、maven-jacoco-plugin生成测试覆盖率报告),可在site阶段整合更多类型的文档。或者通过maven-site-plugin的配置自定义站点模板、logo、导航栏等,使文档风格符合团队规范。

有时候也和自动化部署结合,结合 CI/CD 工具(如 Jenkins),在项目构建成功后自动执行mvn site-deploy,将最新站点部署到服务器,确保文档实时更新。

Maven 构建配置文件

构建配置文件是一系列的配置项的值,可以用来设置或者覆盖 Maven 构建默认值。它允许你在同一个 POM 文件中定义多套配置,在构建时通过指定参数激活特定配置。

使用构建配置文件,你可以为不同的环境,比如说生产环境(Production)和开发(Development)环境,定制构建方式。

配置文件在 pom.xml 文件中使用 activeProfiles 或者 profiles 元素指定,并且可以通过各种方式触发。配置文件在构建时修改 POM,并且用来给参数设定不同的目标环境。

本质上和 Spring 的那一套 profile 是很类似的

构建配置文件大体上有三种类型:

  1. 项目级:在项目的 pom.xml 中定义,仅对当前项目有效。 (最常用,下文示例均基于此)
  2. 用户级:在用户目录的 .m2/settings.xml 中定义,对当前用户的所有项目有效。
  3. 全局级:在 Maven 安装目录的 conf/settings.xml 中定义,对当前机器的所有用户和项目有效。

配置文件的基本结构如下

pom.xml 中,配置文件通过 <profiles> 标签定义,每个配置文件用 <profile> 标签包裹,包含唯一标识(id)和具体配置。基本结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<project>
...
<profiles>
<!-- 第一个配置文件:开发环境 -->
<profile>
<id>dev</id> <!-- 唯一标识,激活时使用 -->
<properties>
<!-- 自定义属性,可在POM中通过${propertyName}引用 -->
<env>development</env>
<db.url>jdbc:mysql://localhost:3306/dev_db</db.url>
</properties>
<dependencies>
<!-- 开发环境特有的依赖 -->
<dependency>
<groupId>com.example</groupId>
<artifactId>dev-tools</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<!-- 开发环境的构建配置(如插件) -->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<debug>true</debug> <!-- 开发环境保留调试信息 -->
</configuration>
</plugin>
</plugins>
</build>
</profile>

<!-- 第二个配置文件:生产环境 -->
<profile>
<id>prod</id>
<properties>
<env>production</env>
<db.url>jdbc:mysql://prod-server:3306/prod_db</db.url>
</properties>
<dependencies>
<!-- 生产环境特有的依赖(如监控工具) -->
<dependency>
<groupId>com.example</groupId>
<artifactId>monitor-agent</artifactId>
<version>2.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<debug>false</debug> <!-- 生产环境关闭调试信息 -->
<optimize>true</optimize> <!-- 开启代码优化 -->
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

上述示例定义了两个配置文件:dev(开发环境)和 prod(生产环境),分别包含不同的属性、依赖和插件配置。

但是,配置文件不会默认生效,需要通过以下方式激活:

  • 命令行激活(最常用)

    通过 -P 参数指定配置文件的 id(多个用逗号分隔):

    1
    2
    3
    4
    5
    # 激活开发环境配置
    mvn clean package -P dev

    # 同时激活多个配置(如dev和test)
    mvn clean package -P dev,test
  • 自动激活

    在配置文件中通过 <activation> 标签定义激活条件,满足条件时自动生效:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <profile>
    <id>windows</id>
    <!-- 当操作系统是Windows时自动激活 -->
    <activation>
    <os>
    <name>Windows</name>
    </os>
    </activation>
    <properties>
    <line.separator>\r\n</line.separator>
    </properties>
    </profile>

    常见的自动激活条件:

    • 操作系统(<os>):如 Windows、Linux;
    • JDK 版本(<jdk>):如1.811
    • 系统属性(<property>):如-Denv=prod时激活;
    • 文件存在 / 不存在(<file>):如<exists>src/main/filters/prod.properties</exists>
  • settings.xml 中通过 <activeProfiles> 标签指定默认激活的配置文件:

    1
    2
    3
    4
    5
    6
    <settings>
    ...
    <activeProfiles>
    <activeProfile>dev</activeProfile> <!-- 默认激活dev配置 -->
    </activeProfiles>
    </settings>

配置文件中可以覆盖或补充 POM 中的大部分配置,核心包括:

  1. 属性(<properties>:定义自定义变量(如环境变量、路径、版本号),在 POM 中通过 ${变量名} 引用。
  2. 依赖(<dependencies><dependencyManagement>:添加或覆盖项目依赖(如开发环境多引入测试工具,生产环境移除)。
  3. 构建配置(<build>
    • 插件配置(<plugins>):如编译参数、打包方式、资源过滤等;
    • 资源目录(<resources>):指定不同环境的资源文件(如 src/main/resources/dev);
    • 输出目录(<outputDirectory>):自定义编译或打包的输出路径。
  4. 仓库(<repositories><pluginRepositories>:指定不同环境的依赖仓库(如开发用内部快照仓库,生产用稳定仓库)。

当多个配置文件同时激活,且配置存在冲突时,优先级规则如下:

  1. 命令行激活的配置文件(-P)优先级最高;
  2. 后续激活的配置文件会覆盖先激活的(如 -P dev,prodprod 覆盖 dev 的冲突配置);
  3. 项目级配置文件优先级高于用户级和全局级。

其实用的最多的也就是根据 JDK 版本切换编译配置,最常用的就是在 settings.xmlpom.xml 中配置默认激活的配置文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<profile>
<id>jdk11</id>
<activation>
<jdk>11</jdk> <!-- JDK11时自动激活 -->
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
</plugins>
</build>
</profile>

IDEA 是可以设置 Maven 默认配置的,避免每次设置 Maven

img
img

找的图,自己懒得截图了

AntRun 集成进入 Maven

上面的例子中,我们使用了 Ant 脚本相关的内容,打印了 Maven 生命周期中的一些内容作为测试

一般下,maven-antrun-plugin 是 Maven 中的一个核心插件,允许用户在 Maven 构建过程中嵌入并执行 Apache Ant 任务。它为 Maven 提供了与 Ant 生态的兼容性,尤其适用于需要复用 Ant 脚本或实现复杂构建逻辑的场景。

AntRun 插件的用途还是很广泛的:

  • 扩展构建功能:虽然 Maven 自身提供了丰富的构建功能,但某些特定的任务可能没有现成的 Maven 插件来实现,而 Ant 拥有大量的任务库,AntRun 插件可以让你在 Maven 构建中执行 Ant 任务,弥补 Maven 功能上的不足。
  • 兼容旧项目:对于一些从 Ant 迁移到 Maven 的项目,部分构建逻辑可能仍然依赖于 Ant 任务,使用 AntRun 插件可以在不改变太多现有逻辑的情况下,将这部分功能集成到 Maven 构建流程中。
  • 自定义构建步骤:方便在 Maven 生命周期的各个阶段插入自定义的构建步骤,例如在编译前执行一些脚本,在打包后执行文件复制、修改文件权限等操作。

在 Maven 项目中使用 AntRun 插件,通常不需要额外安装,因为 Maven 会在构建时自动从中央仓库下载插件。一般在 pom.xml 文件的 <build><plugins> 标签内配置该插件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version> <!-- 选择合适的版本 -->
<executions>
<execution>
<id>id-example</id> <!-- 给执行配置一个唯一标识 -->
<phase>compile</phase> <!-- 绑定到Maven生命周期的某个阶段,这里绑定到compile阶段 -->
<goals>
<goal>run</goal> <!-- 执行AntRun插件的run目标,用于运行Ant任务 -->
</goals>
<configuration>
<tasks>
<!-- 这里编写具体的Ant任务 -->
<echo>Executing before compilation</echo>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

上述配置表示将 AntRun 插件的 run 目标绑定到 compile 阶段,当执行 mvn compile 命令时,就会先执行配置的 Ant 任务,这里是输出一条提示信息。

关键配置项 :指定 Ant 任务绑定的 Maven 生命周期阶段。 :通常为 run,表示执行 Ant 任务。 :定义 Ant 任务的具体内容,支持所有标准 Ant 任务(如 等)。 :可选参数,设置为 true 可跳过该任务的执行。

常见的 Ant 任务及在 AntRun 中的使用:

  • 文件操作任务

    复制文件

    1
    2
    3
    <tasks>
    <copy file="src/main/resources/config.properties" todir="target/classes" />
    </tasks>

    这个任务会将 src/main/resources 目录下的 config.properties 文件复制到 target/classes 目录,常用于资源文件的处理。

  • 删除文件或目录

    1
    2
    3
    4
    <tasks>
    <delete file="target/temp.txt" /> <!-- 删除单个文件 -->
    <delete dir="target/tempDir" /> <!-- 删除目录 -->
    </tasks>
  • 执行脚本任务

    • 执行 Shell 脚本(在 Linux 或 macOS 系统)

      1
      2
      3
      4
      5
      6
      <tasks>
      <exec executable="sh">
      <arg value="-c" />
      <arg value="echo 'This is a shell script execution'" />
      </exec>
      </tasks>
    • 执行批处理脚本(在 Windows 系统)

      1
      2
      3
      4
      5
      6
      <tasks>
      <exec executable="cmd">
      <arg value="/c" />
      <arg value="echo This is a batch script execution" />
      </exec>
      </tasks>
  • 属性操作任务

    设置属性

    1
    2
    3
    4
    <tasks>
    <property name="my.version" value="1.0" />
    <echo message="The version is ${my.version}" />
    </tasks>

​ 通过 <property> 标签设置属性,然后在其他任务中可以通过 ${属性名} 的方式引用。