Article

项目构建 Maven

更新于:2026-07-14

第一章:Maven 概述与环境搭建

1.1 什么是 Maven

概念名称说明注意事项
MavenMaven 是一个基于项目对象模型(POM)的自动化构建工具,主要用于 Java 项目的构建、依赖管理和项目信息管理。它通过标准化的构建流程和约定优于配置的原则,简化项目构建过程。Maven 不仅是构建工具,更是项目管理工具,可生成项目报告、站点文档等。
POM (Project Object Model)项目对象模型,是 Maven 的核心。每个 Maven 项目都包含一个 pom.xml 文件,定义了项目的配置信息,如坐标、依赖、插件、构建配置等。pom.xml 是 Maven 项目的配置中心,必须正确编写以确保项目正常构建。
构建(Build)将源代码转换为可执行程序或可部署构件的过程,包括编译、测试、打包、部署等步骤。Maven 提供标准化的生命周期来管理构建过程。构建过程可重复、自动化,避免手动操作带来的错误。
约定优于配置(Convention over Configuration)Maven 提供默认的项目结构和行为,开发者无需手动配置即可快速开始。只有在需要偏离默认约定时才需额外配置。减少配置复杂度,提升开发效率,但需熟悉默认约定(如 src/main/java 存放源码)。

1.2 Maven 的核心特性与优势

特性名称说明注意事项
标准化构建流程Maven 定义了清晰的构建生命周期(如 compiletestpackageinstalldeploy),所有项目遵循统一流程。开发者无需从零设计构建脚本,提升团队协作效率。
依赖管理自动下载和管理项目所需的第三方库(JAR 包),解决手动下载、版本混乱、依赖冲突等问题。需合理使用依赖范围(如 testprovided)避免运行时错误。
项目信息管理通过 pom.xml 统一管理项目名称、版本、开发者、许可证等元数据。有助于生成项目文档、报告,提升项目可维护性。
插件机制构建任务由插件完成,Maven 提供大量官方插件(如 compilersurefire),支持自定义插件。插件可扩展性强,但需注意版本兼容性。
多模块项目支持支持将大型项目拆分为多个子模块,统一构建和管理。适用于复杂系统,需合理设计模块划分和依赖关系。
仓库机制本地、远程、中央仓库协同工作,实现依赖的存储、共享和分发。私服(如 Nexus)可用于企业内部依赖管理,提升安全性和构建速度。
可重复构建相同输入(pom.xml 和源码)始终产生相同输出,确保构建一致性。有利于持续集成(CI)和生产部署。

1.3 Maven 与构建工具对比(Ant、Gradle)

对比维度MavenAntGradle注意事项
构建方式基于约定和生命周期,声明式配置基于目标(target)的命令式脚本基于 Groovy/Kotlin DSL 的声明式 + 脚本式Maven 更规范,Ant 更灵活,Gradle 兼具灵活性与性能。
配置文件pom.xml(XML 格式)build.xml(XML 格式)build.gradle(Groovy/Kotlin)Gradle 配置更简洁,Maven 和 Ant 的 XML 易冗长。
依赖管理内置强大依赖管理,支持自动下载和传递无内置依赖管理,需手动管理 JAR 包内置依赖管理,支持 Maven/Gradle 仓库Ant 依赖管理繁琐,Maven 和 Gradle 更适合现代项目。
执行效率一般一般高(增量构建、缓存、并行执行)Gradle 构建速度显著优于 Maven 和 Ant,尤其在大型项目中。
学习曲线中等,需理解 POM 和生命周期简单(基础脚本),复杂时陡峭中等偏高(需学习 DSL)Maven 概念较多,但结构清晰;Gradle 功能强大但语法需学习。
社区与生态非常成熟,广泛用于企业项目老牌工具,新项目较少使用快速增长,Android 官方推荐Maven 生态最丰富,Gradle 在新项目中越来越流行。
多语言支持主要支持 Java支持多种语言(通过任务扩展)支持 Java、Kotlin、Scala、Android 等Ant 和 Gradle 更适合多语言项目。
生命周期预定义完整生命周期(defaultcleansite无预定义生命周期,完全自定义支持标准生命周期,可自定义Maven 生命周期标准化程度高,利于团队统一。

1.4 Maven 环境安装与配置

步骤操作说明注意事项
安装 JDKMaven 依赖 Java 环境,需先安装 JDK 8 或更高版本。确保 JAVA_HOME 环境变量正确指向 JDK 安装目录,而非 JRE。
下载 Maven从官网 https://maven.apache.org 下载二进制压缩包(apache-maven-x.x.x-bin.zip)。建议选择最新稳定版本,避免使用过旧版本。
解压 Maven 包将下载的压缩包解压到指定目录(如 C:\maven/opt/maven)。解压路径避免包含空格或中文字符,防止后续构建出错。
配置环境变量设置 MAVEN_HOMEM2_HOME 指向 Maven 解压目录,并将 %MAVEN_HOME%\bin(Windows)或 $MAVEN_HOME/bin(Linux/macOS)添加到 PATH。确保命令行可全局执行 mvn 命令。
验证安装打开终端,执行 mvn -vmvn --version正确输出 Maven 版本、Java 版本、Maven 主目录等信息表示安装成功。
配置 settings.xml可选:修改 %MAVEN_HOME%\conf\settings.xml 文件,配置本地仓库路径、镜像、代理等。企业环境中常配置私服镜像以提升依赖下载速度。

1.5 验证安装与基础命令测试

命令名称语法用途代码示例注意事项
显示 Maven 版本信息mvn -vmvn --version验证 Maven 是否安装成功,查看 Maven、JDK 和操作系统版本等环境信息。mvn -v必须正确显示 Maven 版本、Java 版本和 MAVEN_HOME 路径,否则安装或配置有误。
创建简单 Maven 项目mvn archetype:generate使用 archetype 插件生成标准 Maven 项目骨架。mvn archetype:generate执行后需交互式选择模板(如 maven-archetype-quickstart)并填写 groupId、artifactId 等。
强制跳过交互式输入创建项目mvn archetype:generate -DgroupId=com.example -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false非交互式快速生成最简单的 Maven Java 项目。如上所示-D 参数用于指定项目坐标和模板;-DinteractiveMode=false 禁用交互模式。
编译主源代码mvn compilesrc/main/java 下的 Java 源文件编译为 class 文件,输出到 target/classesmvn compile若依赖缺失会自动下载;编译失败时检查源码语法和依赖配置。
编译并运行单元测试mvn test编译 src/test/java 下的测试代码,并执行所有单元测试。mvn test测试结果输出在控制台,失败的测试会标记;确保测试类遵循命名规范(如 *Test)。
打包项目mvn package对项目进行编译、测试后,根据 pom.xml 中的 packaging 类型(如 jar、war)打包。mvn package打包文件生成在 target/ 目录下;若测试失败默认中断打包。
将构件安装到本地仓库mvn install将当前项目打包后的构件(如 JAR)安装到本地仓库(~/.m2/repository),供其他项目依赖。mvn install是模块化开发中常用命令,使当前项目可作为依赖被其他本地项目使用。
清理构建目录mvn clean删除 target/ 目录及其内容,清除上次构建产生的文件。mvn clean建议在重新构建前执行,确保构建干净;不会影响源码和配置文件。
打印项目依赖树mvn dependency:tree显示项目直接和传递依赖的层级结构,用于分析依赖冲突和冗余。mvn dependency:tree输出信息量大,可结合 grep 过滤;是排查依赖问题的核心命令。
下载源码和文档mvn dependency:sources / mvn dependency:resolve -Dclassifier=javadoc分别尝试下载依赖项的源码和 JavaDoc 文档,便于 IDE 调试和查看。mvn dependency:sources并非所有依赖都提供源码或文档,部分可能下载失败。

第二章:Maven 核心概念

2.1 项目对象模型(POM)

概念名称说明注意事项
POM (Project Object Model)项目对象模型,是 Maven 的核心概念。每个 Maven 项目都必须包含一个 pom.xml 文件,它以 XML 格式定义了项目的配置信息,包括项目坐标、依赖、构建配置、插件、属性等。pom.xml 是 Maven 项目的基础,Maven 通过读取该文件来执行构建任务。
父 POM (Super POM)Maven 内置的默认 POM,所有项目 POM 都隐式继承它。它定义了默认的仓库、插件版本、目录结构等。可通过 mvn help:effective-pom 查看实际生效的 POM。理解 Super POM 有助于明白为何某些配置(如源码目录)无需显式声明。
最小化 POM一个合法的 pom.xml 至少需要包含 modelVersiongroupIdartifactIdversion 四个元素。modelVersion 通常为 4.0.0,表示 POM 模型版本。
继承 (Inheritance)子项目可以继承父项目的 POM 配置(通过 <parent> 元素),实现配置复用,常用于多模块项目。父 POM 通常打包为 pom 类型,不包含实际代码。
聚合 (Aggregation)又称多模块项目,一个父项目可以聚合多个子模块,通过 <modules> 元素列出子模块目录,实现统一构建。聚合 POM 的 packaging 必须为 pom
可变性 (Reactor)在多模块构建中,Maven 的 Reactor 机制会分析模块间的依赖关系,自动确定构建顺序。构建顺序不一定按 pom.xml 中模块声明的顺序,而是按依赖拓扑排序。

2.2 坐标(GroupId、ArtifactId、Version)

坐标元素说明注意事项
groupId定义当前 Maven 项目所属的组织或团体,通常与域名反向对应(如 com.example)。用于区分不同组织的项目。建议使用公司或组织域名反写,确保全局唯一性。
artifactId定义当前项目在 groupId 下的唯一标识,通常是项目名称(如 my-web-app)。与 groupId 共同确定项目位置。应简洁明了,避免使用特殊字符。
version定义当前项目的版本号,如 1.0.02.1.3-SNAPSHOT 等。SNAPSHOT 表示开发中的快照版本。发布版本(无 SNAPSHOT)是稳定的;快照版本每次构建都会检查更新。
packaging定义项目的打包类型,常见值有 jarwarpomear 等。默认为 jar。影响构建生命周期和输出文件。不同 packaging 触发不同的默认插件绑定(如 war 会绑定 maven-war-plugin)。
classifier可选元素,用于区分同一 artifactId 和 version 的不同构建产物(如 sourcesjavadoc)。不能直接定义在 pom.xml 中,由插件生成(如 mvn source:jar 生成 *-sources.jar)。

示例坐标定义:

groupId: com.example
artifactId: my-app
version: 1.0.0-SNAPSHOT
packaging: jar

该坐标唯一确定一个构件,在仓库中的路径为:com/example/my-app/1.0.0-SNAPSHOT/my-app-1.0.0-SNAPSHOT.jar

2.3 仓库(本地、远程、中央仓库)

仓库类型说明注意事项
本地仓库 (Local Repository)位于用户本地磁盘(默认 ~/.m2/repository),存储从远程仓库下载的依赖和本地安装的构件。Maven 优先从本地查找依赖。可通过 settings.xml 修改路径;删除后可重新下载,但会增加构建时间。
中央仓库 (Central Repository)Maven 官方维护的公共仓库(https://repo.maven.apache.org/maven2),包含大量开源 Java 库。所有 Maven 项目默认可访问。不包含所有开源库(如某些商业库或较新版本),需额外配置其他远程仓库。
远程仓库 (Remote Repository)项目自定义的第三方仓库,可以是公共仓库(如 JCenter 已停用)或企业私有仓库(如 Nexus、Artifactory)。需在 pom.xmlsettings.xml 中配置,用于获取中央仓库没有的依赖。
私服 (Private Repository)企业内部搭建的远程仓库,用于统一管理内部构件、缓存外部依赖、提升安全性与构建速度。可代理中央仓库,减少外网访问;支持权限控制和审计。
镜像仓库 (Mirror)为远程仓库设置的代理,所有对原仓库的请求将被重定向到镜像。常用于加速下载(如国内使用阿里云镜像)。settings.xml 中配置,使用 <mirrorOf> 指定被代理的仓库(如 central)。

仓库查找顺序: 本地仓库 → 镜像仓库(若配置)→ 远程仓库 → 中央仓库

2.4 依赖管理机制

机制名称说明注意事项
直接依赖 (Direct Dependency)项目在 pom.xml<dependencies> 中直接声明的依赖。明确列出项目所需库,版本由 dependencydependencyManagement 控制。
传递性依赖 (Transitive Dependency)Maven 自动解析并引入直接依赖所依赖的库。例如 A 依赖 B,B 依赖 C,则 C 是 A 的传递性依赖。可能导致依赖冲突或引入不必要的库,需用依赖树分析。
依赖范围 (Scope)控制依赖在不同构建阶段的可见性和使用范围,如 compiletestprovided 等。正确使用 scope 可避免运行时类冲突(如 provided 不打包到最终构件)。
依赖调解 (Dependency Mediation)当存在多个版本的同一依赖时,Maven 采用”路径最近优先”原则选择版本。若路径相同,则”先声明优先”。可通过在 pom.xml 中直接声明依赖来强制指定版本。
依赖排除 (Exclusion)使用 <exclusions> 排除某个依赖的特定传递性依赖,防止其被引入。常用于排除冲突或过时的传递依赖。
可选依赖 (Optional)使用 <optional>true</optional> 标记依赖为可选,表示该依赖不会被传递。适用于功能扩展库,使用者需显式声明才能使用。
依赖管理 (Dependency Management)在父 POM 的 <dependencyManagement> 中统一声明依赖版本,子模块继承但不自动引入。实现版本集中管理,避免版本混乱,是多模块项目的最佳实践。

2.5 构建生命周期(Build Lifecycle)

生命周期名称包含阶段(部分)用途注意事项
defaultvalidate → compile → test → package → verify → install → deploy处理项目部署的核心生命周期,从源码到发布。最常用,mvn compilemvn package 等命令即执行该周期的特定阶段。
cleanpre-clean → clean → post-clean清理项目,删除 target/ 等构建输出目录。mvn clean 执行该周期,确保干净构建。
sitepre-site → site → post-site → site-deploy生成项目站点文档,包含项目信息、报告、依赖列表等。mvn site 生成文档,mvn site-deploy 发布文档。
概念名称说明注意事项
阶段 (Phase)生命周期中的一个步骤,每个阶段代表构建过程的一个特定任务(如 compile 编译源码)。阶段按顺序执行,调用某一阶段时,会自动执行之前的所有阶段。
绑定 (Binding)插件目标(Goal)与生命周期阶段的关联。例如 compiler:compile 默认绑定到 compile 阶段。可自定义绑定,改变默认行为。
跳过阶段可通过参数跳过某些阶段,如 -Dmaven.test.skip=true 跳过测试和编译测试代码。谨慎使用,确保跳过不会影响构建完整性。

2.6 插件(Plugins)与目标(Goals)

概念名称说明注意事项
插件 (Plugin)Maven 的功能单元,用于执行具体的构建任务(如编译、打包、测试)。插件由 groupIdartifactIdversion 唯一标识。大部分插件由 org.apache.maven.plugins 提供,可自定义开发。
目标 (Goal)插件中的一个具体任务。一个插件可包含多个目标(如 compiler 插件有 compiletestCompile)。目标是实际执行的最小单元。
命令格式mvn [plugin-prefix]:[goal]plugin-prefix 是插件的简称(如 compiler),可在中央仓库查询。
默认绑定Maven 根据项目的 packaging 类型自动绑定插件目标到生命周期阶段。jar 项目自动绑定 maven-compiler-plugin:compilecompile 阶段。
显式配置插件pom.xml<build><plugins> 中配置插件版本、参数等。建议显式声明插件版本,避免使用默认版本带来的不确定性。
插件前缀插件的简称,用于命令行调用(如 tomcat7:run)。映射关系存储在插件元数据中。并非所有插件都有前缀,可通过 mvn help:describe -Dplugin=groupId:artifactId 查看。

示例:常用插件目标

插件前缀目标名称用途命令示例
compilercompile编译主源码mvn compiler:compile
surefiretest执行单元测试mvn surefire:test
jarjar打包为 JAR 文件mvn jar:jar
execjava运行 Java 类mvn exec:java -Dexec.mainClass="com.example.Main"
dependencytree显示依赖树mvn dependency:tree

第三章:Maven 项目结构与创建

3.1 标准项目目录结构

目录/文件路径说明注意事项
src/main/java存放项目的主 Java 源代码文件(.java)。包结构需与 pom.xml 中的 groupIdartifactId 对应。
src/main/resources存放主代码所需的资源文件,如配置文件(.properties.xml)、静态资源等。编译后这些文件会被复制到输出目录的 classpath 下。
src/test/java存放单元测试的 Java 源代码文件(如 JUnit 测试类)。测试代码不会被打包到最终构件中。
src/test/resources存放测试代码所需的资源文件,如测试专用配置。仅在测试阶段可用,不包含在发布包中。
src/main/webapp(仅 Web 项目)存放 Web 应用资源,如 JSP、HTML、WEB-INF 等。packagingwar 时需要此目录。
target/Maven 构建过程的输出目录,编译后的 class 文件、打包的 JAR/WAR 等均在此。可安全删除,执行构建命令后会重新生成;不应提交到版本控制系统。
pom.xml项目核心配置文件,定义项目坐标、依赖、插件、构建配置等。必须位于项目根目录;是 Maven 识别项目的标志。
src/main/filters存放属性过滤文件(.properties),用于资源文件中的占位符替换。需在 pom.xml 中启用资源过滤功能。
src/assembly存放程序集描述文件,用于自定义打包内容(配合 maven-assembly-plugin)。非必需,用于复杂打包需求。
src/site存放项目站点文档的源文件。用于生成项目文档网站。

示例结构:

my-app/
├── pom.xml
└── src/
    ├── main/
    │   ├── java/
    │   │   └── com/
    │   │       └── example/
    │   │           └── App.java
    │   └── resources/
    │       └── application.properties
    └── test/
        ├── java/
        │   └── com/
        │       └── example/
        │           └── AppTest.java
        └── resources/
            └── test-config.properties

3.2 手动创建 Maven 项目

步骤操作说明注意事项
创建项目根目录在文件系统中创建项目主目录(如 my-app)。目录名通常与 artifactId 一致。
创建标准源码目录在项目根目录下创建 src/main/javasrc/test/java 目录。必须严格遵循 Maven 默认目录结构,否则无法正确编译。
编写主程序类src/main/java 下按包路径创建 Java 类文件(如 com/example/App.java)。类中应包含主方法(public static void main)以便运行。
编写测试类src/test/java 下创建对应的测试类(如 com/example/AppTest.java)。建议使用 JUnit 框架,测试类名通常以 Test 结尾。
创建 pom.xml在项目根目录创建 pom.xml 文件,至少包含 modelVersiongroupIdartifactIdversionpackaging 默认为 jar,若为 Web 项目需设为 war
添加必要依赖<dependencies> 中添加 junit-jupiter-api 等测试依赖。测试依赖 scope 应设为 test
验证项目结构执行 mvn compile 编译主代码,mvn test 运行测试。若无错误表示项目结构和配置正确。

最小化 pom.xml 示例:

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>my-app</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.7.0</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

3.3 使用 archetype 插件生成项目

方法名称语法用途代码示例注意事项
交互式生成项目mvn archetype:generate启动向导模式,通过交互选择模板并输入项目信息生成项目骨架。mvn archetype:generate首次使用需下载 archetype 目录,可能较慢;适合学习和尝试不同模板。
非交互式生成简单 Java 项目mvn archetype:generate -DgroupId=... -DartifactId=... -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false快速生成包含基本结构和示例代码的 Java 项目,无需交互。mvn archetype:generate -DgroupId=com.example -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false最常用方式,适合脚本化创建项目。
生成 Web 项目mvn archetype:generate -DgroupId=... -DartifactId=... -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false生成标准的 Maven Web 项目结构,包含 webapp 目录和基础 web.xmlmvn archetype:generate -DgroupId=com.example -DartifactId=my-web -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false生成的 web.xml 版本较旧,可根据需要升级。
指定 archetype 版本... -DarchetypeVersion=1.4明确指定使用的 archetype 模板版本,避免使用默认或过时版本。... -DarchetypeVersion=1.4建议显式指定版本以保证一致性。
指定远程仓库 URL... -DarchetypeCatalog=internal -DremoteRepositories=https://...当使用私有仓库中的 archetype 时,指定其 URL。... -DarchetypeCatalog=remote -DremoteRepositories=https://nexus.example.com/repository/maven-public企业环境中常用于内部项目模板。
列出可用 archetypemvn archetype:generate -Dfilter=maven-archetype-在交互模式下,通过 filter 快速筛选 archetype 列表。mvn archetype:generate -Dfilter=maven-archetype-方便查找官方 archetype。

3.4 多模块项目结构简介

概念名称说明注意事项
聚合 POM (Aggregator)父项目 pom.xml 中通过 <modules> 元素列出所有子模块,实现统一构建。父项目 packaging 必须为 pom执行 mvn install 会在父目录构建所有模块。
继承 POM (Parent)子模块通过 <parent> 元素继承父 POM 的配置(如依赖管理、插件、属性)。父 POM 可集中管理版本,减少重复配置。
模块目录每个子模块是一个独立的 Maven 项目,拥有自己的 pom.xml 和标准目录结构。模块目录名通常与 artifactId 一致。
构建顺序Maven Reactor 机制自动分析模块间依赖,确定构建顺序。若模块 A 依赖模块 B,则 B 必须先于 A 构建。
相对路径<relativePath> 元素指定父 POM 的位置,默认为 ../pom.xml若父 POM 在上级目录可省略;否则需明确指定。

示例多模块结构:

my-parent/
├── pom.xml          (packaging: pom, 包含 <modules>)
├── module-a/
│   └── pom.xml      (<parent> 指向 my-parent)
├── module-b/
│   └── pom.xml      (<parent> 指向 my-parent,可能依赖 module-a)
└── module-web/
    └── pom.xml      (<parent> 指向 my-parent,依赖 module-a 和 module-b)

父 POM 片段示例:

<packaging>pom</packaging>
<modules>
    <module>module-a</module>
    <module>module-b</module>
    <module>module-web</module>
</modules>

第四章:POM 文件详解

4.1 pom.xml 基本结构

元素名称说明注意事项
<project>根元素,所有其他元素都包含在其中。必须存在,且是 XML 文档的顶层标签。
xmlns定义 POM 的命名空间,固定为 http://maven.apache.org/POM/4.0.0声明使用的 POM 模型版本。
xsi:schemaLocation指定 XML Schema 位置,用于 IDE 验证和自动补全。开发时有助于减少配置错误。
<modelVersion>指定 POM 模型版本,当前必须为 4.0.0固定值,表示使用 Maven 2/3 的 POM 格式。
<groupId>项目所属组织标识。通常与公司域名反向对应(如 com.example)。
<artifactId>项目在组织内的唯一标识。通常是项目名称,简洁明确。
<version>项目版本号。可使用 SNAPSHOT 表示开发中版本。
<packaging>打包类型,默认为 jar常见值:jarwarpomear
<name>项目的描述性名称,用于生成文档或展示。非必需,但建议填写以增强可读性。
<description>项目详细描述。非必需,可用于生成项目站点。
<url>项目主页 URL。非必需,企业项目可指向内部文档系统。

最小化完整结构示例:

<project xmlns="http://maven.apache.org/POM/4.0.0">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>my-app</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>jar</packaging>
</project>

4.2 基础配置元素(modelVersionpackaging 等)

元素名称说明注意事项
<modelVersion>POM 模型版本,当前唯一有效值为 4.0.0必需,Maven 通过此值解析 POM 文件结构。
<groupId>项目所属组织的唯一标识符。建议使用反向域名确保全局唯一性。
<artifactId>项目自身的唯一标识符。通常小写,使用连字符分隔单词(如 my-web-app)。
<version>项目版本号,格式通常为 主版本.次版本.修订号[-限定符]-SNAPSHOT 表示快照版本,每次构建都会更新;发布版本应去掉 SNAPSHOT。
<packaging>项目打包类型,影响构建生命周期和默认插件绑定。默认为 jar;Web 项目用 war;聚合/父项目用 pom
<name>项目的可读名称,用于展示。非必需,但有助于团队协作和文档生成。
<description>项目功能的简要描述。非必需,建议填写。
<url>项目主页或文档地址。非必需,可用于链接到 Confluence 或 GitHub 页面。
<inceptionYear>项目起始年份。非必需,用于版权信息等。
<organization>组织信息,包含 <name><url>非必需,多用于开源项目。
<licenses>项目使用的许可证信息(如 Apache License 2.0)。开源项目必需,企业项目可选。
<developers>开发者列表,包含姓名、邮箱、角色等。非必需,用于项目管理和贡献记录。

4.3 依赖声明(dependencies

元素名称说明注意事项
<dependencies>包含一个或多个 <dependency> 元素,声明项目直接依赖。是依赖管理的核心部分。
<dependency>声明一个具体的依赖项。必须包含 groupIdartifactIdversion
<groupId>被依赖库的组织 ID。必需,与中央仓库坐标一致。
<artifactId>被依赖库的项目 ID。必需。
<version>被依赖库的版本号。必需,除非由 dependencyManagement 控制。
<type>依赖类型,默认为 jar。其他如 pomwarejb 等。通常省略,Maven 自动推断。
<scope>依赖的作用范围(如 compiletest)。见 4.4 节详解。
<optional>是否为可选依赖(true/false)。见 4.7 节详解。
<exclusions>排除该依赖的传递性依赖。见 4.6 节详解。

依赖声明示例:

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.2</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>5.3.21</version>
    </dependency>
</dependencies>

4.4 依赖范围(scope)

范围名称编译期可见测试期可见运行期可见传递性用途说明注意事项
compile默认范围,适用于所有阶段,依赖会打包到最终构件中。用于核心业务逻辑依赖(如 Spring、Hibernate)。
test仅在测试编译和执行阶段可用,不会被打包或部署。用于单元测试框架(如 JUnit、TestNG)。
provided编译和测试需要,但期望 JDK 或运行容器(如 Tomcat)提供,不打包。Web 应用中用于 Servlet API、JSP API 等。
runtime编译不需要,但测试和运行需要。用于 JDBC 驱动、日志实现等接口与实现分离的场景。
system类似 provided,但必须通过 systemPath 指定本地 JAR 路径。不推荐使用,破坏了可移植性;应优先安装到本地仓库。
import----仅用于 <dependencyManagement> 中,导入其他 POM 的依赖管理配置。packaging 必须为 pom;常用于引入 Spring Boot BOM。

4.5 依赖传递与冲突解决

机制名称说明注意事项
传递性依赖A 依赖 B,B 依赖 C,则 A 会自动依赖 C,无需在 A 的 pom.xml 中声明。可能引入大量间接依赖,使用 mvn dependency:tree 查看完整依赖树。
路径最近优先当存在多个版本的同一依赖时,Maven 选择依赖路径最短的版本。例如 A→B→C(1.0) 和 A→D→E→C(2.0),则选择 C(1.0),因为路径更短。
先声明优先若路径长度相同,则先在 pom.xml 中声明的依赖其传递依赖优先被选用。依赖声明顺序可能影响最终版本选择,建议显式声明关键依赖版本。
版本锁定<dependencyManagement> 中统一声明版本,确保一致性。多模块项目最佳实践,避免版本碎片化。
依赖树分析使用 mvn dependency:tree 命令查看所有直接和传递依赖及其版本。是排查冲突的核心手段,可结合 -Dverbose 显示被忽略的依赖。
冲突表现类找不到(ClassNotFoundException)、方法不存在(NoSuchMethodError)等。通常由不同版本的同一库引起,需通过依赖树定位并排除或升级。

4.6 依赖排除(exclusions

元素名称说明注意事项
<exclusions>包含一个或多个 <exclusion> 元素,用于排除传递性依赖。放在 <dependency> 内部。
<exclusion>定义一个要排除的依赖项。必须指定 groupIdartifactId
<groupId>要排除的依赖的组织 ID。必需。
<artifactId>要排除的依赖的项目 ID。必需。

排除示例(排除 log4j):

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>5.3.21</version>
    <exclusions>
        <exclusion>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>

4.7 可选依赖(optional

元素名称说明注意事项
<optional>布尔值(true/false),标记依赖是否为可选。默认为 false

可选依赖示例:

<dependency>
    <groupId>com.example</groupId>
    <artifactId>email-support</artifactId>
    <version>1.0.0</version>
    <optional>true</optional>
</dependency>

说明: 当其他项目依赖本项目时,不会自动继承 email-support 这个依赖,使用者必须显式声明才能使用邮件功能。

4.8 属性(properties)配置

属性类型语法示例用途说明注意事项
内建属性${basedir}指向项目根目录。常用于文件路径引用。
POM 属性${project.version}引用当前 POM 的元素值,如 versiongroupId 等。可简化配置,避免重复。
自定义属性<my.version>1.2.3</my.version>${my.version}用户在 <properties> 中定义的属性。常用于统一管理版本号。
Settings 属性${settings.localRepository}引用 settings.xml 中的值。如本地仓库路径。
Java 系统属性${java.home}JVM 系统属性,可通过 System.getProperties() 获取。os.nameuser.home 等。
环境变量属性${env.JAVA_HOME}操作系统环境变量。注意跨平台兼容性。

属性配置示例:

<properties>
    <java.version>8</java.version>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
    <spring.version>5.3.21</spring.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

4.9 构建配置(build

元素名称说明注意事项
<build>构建配置的根元素,包含最终名称、目录、资源、插件等。非必需,但通常用于自定义构建行为。
<finalName>指定打包后的文件名(不含扩展名)。-
<directory>指定构建输出目录,默认为 target可修改,但不推荐。
<sourceDirectory>主源码目录,默认为 src/main/java可覆盖默认约定。
<testSourceDirectory>测试源码目录,默认为 src/test/java-
<resources>配置主资源文件目录及其过滤行为。见 4.11 节详解。
<testResources>配置测试资源文件目录。默认为 src/test/resources
<plugins>声明构建过程中使用的插件及其配置。见 4.10 节详解。
<pluginManagement>定义插件的默认配置,供子模块继承,避免重复配置。多模块项目中用于集中管理插件版本和配置。

4.10 插件配置(plugins

元素名称说明注意事项
<plugins>包含一个或多个 <plugin> 元素。放在 <build> 下。
<plugin>声明一个插件。必须包含 groupIdartifactIdversion
<groupId>插件的组织 ID,通常为 org.apache.maven.plugins-
<artifactId>插件的项目 ID,如 maven-compiler-plugin-
<version>插件版本。建议显式声明,避免使用默认版本。
<configuration>插件的配置参数,以 XML 形式传递给插件。不同插件支持不同参数。
<executions>定义插件目标的执行时机(绑定到哪个生命周期阶段)。可覆盖默认绑定。
<goals>指定要执行的插件目标。compiletestCompile
<phase>绑定到的生命周期阶段。compilepackage

插件配置示例(编译插件):

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <source>8</source>
                <target>8</target>
            </configuration>
        </plugin>
    </plugins>
</build>

4.11 资源文件管理(resources

元素名称说明注意事项
<resources>定义主资源文件的来源目录和处理方式。可包含多个 <resource>
<resource>一个资源目录的配置。至少包含 <directory>
<directory>资源文件所在的目录,默认为 src/main/resources可指定其他路径。
<includes>包含的文件模式列表(如 **/*.xml)。若未指定,则包含所有文件。
<excludes>排除的文件模式列表(如 **/*.txt)。<includes> 结合使用进行精细控制。
<filtering>是否启用资源过滤(替换 ${} 占位符)。设为 true 时,会用 <properties> 中的值替换文件中的占位符。
<targetPath>资源文件复制到的目标路径(相对于构建输出目录)。默认为根目录。
<testResources>测试资源的配置,结构与 <resources> 相同。默认目录为 src/test/resources

资源过滤示例:

<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
            <includes>
                <include>**/application.properties</include>
            </includes>
        </resource>
    </resources>
</build>

application.properties 内容:

db.url=${db.host}:${db.port}/${db.name}

构建时会被替换为 <properties> 中定义的值。

第五章:Maven 依赖管理

5.1 依赖解析机制

机制名称说明注意事项
本地仓库查找Maven 首先在本地仓库(默认 ~/.m2/repository)中查找依赖的元数据(如 maven-metadata.xml)和构件(JAR 文件)。若存在且版本匹配,则直接使用,无需网络请求。
中央仓库查询若本地仓库不存在或元数据过期(SNAPSHOT 版本),Maven 会查询远程仓库(默认中央仓库 https://repo.maven.apache.org/maven2/)。可通过 settings.xml 配置镜像(mirror)加速下载。
依赖传递Maven 自动解析依赖的依赖(传递性依赖),构建完整的依赖图。使用 mvn dependency:tree 查看完整依赖树。
SNAPSHOT 版本处理对于 SNAPSHOT 版本,Maven 会检查远程仓库是否有更新(基于时间戳),若有则下载最新快照。可通过 -nsu-U 参数控制更新策略。
POM 解析下载依赖时,不仅下载 JAR,还会下载对应的 POM 文件,以解析其自身的依赖关系。这是实现传递性依赖的基础。
版本范围支持支持动态版本声明(如 [1.0,2.0)LATESTRELEASE),但不推荐在生产项目中使用。动态版本可能导致构建不稳定,建议锁定具体版本。
依赖冲突检测在解析过程中,Maven 会识别同一库的不同版本,并根据调解原则选择最终版本。冲突可能导致运行时错误,需通过依赖树分析解决。

5.2 依赖调解原则

原则说明示例
路径最近优先当同一个依赖有多个版本时,选择依赖树中路径最短的那个版本。A → B → C(1.0) / A → D → E → C(2.0),选择 C(1.0),因为路径长度为 2 < 4。
第一声明优先如果依赖路径长度相同,则选择在 pom.xml 中先声明的依赖所引入的传递依赖版本。A → B → C(1.0) / A → F → C(2.0),若 B 在 F 之前声明,则选择 C(1.0)。
依赖管理覆盖<dependencyManagement> 中显式声明的版本优先级最高,会强制覆盖传递性依赖的版本。在父 POM 的 dependencyManagement 中声明 log4j 2.17.0,则所有模块都使用此版本。
作用域影响不同作用域的依赖在不同阶段参与调解。例如,test 作用域依赖不参与运行时类路径构建。编译时只考虑 compileprovided;运行时考虑 runtimecompile

5.3 依赖作用域详解

作用域编译测试运行传递典型用途注意事项
compile核心业务逻辑(Spring Core, Guava)默认作用域,适用于大部分依赖。
providedServlet API, JSP API, Tomcat Embed由 JDK 或容器提供,打包时不包含。
runtimeJDBC Driver (MySQL), Logging Impl (Logback)编译时不需要 API,运行时需要实现。
testJUnit, Mockito, TestNG仅用于测试代码,不打包。
system本地私有 JAR(非 Maven 管理)必须用 systemPath 指定路径,破坏可移植性,不推荐。
import----引入 BOM(Bill of Materials)仅用于 <dependencyManagement>packaging 必须为 pom

关键区别:

  • provided vs runtimeprovided 是编译和测试需要但运行环境已提供;runtime 是编译不需要但运行和测试需要。
  • compile vs systemsystem 依赖必须手动管理 JAR 文件,而 compile 由 Maven 自动下载。

5.4 使用 dependencyManagement 统一版本管理

特性说明注意事项
集中声明在父 POM 的 <dependencyManagement> 中统一定义依赖的 groupIdartifactIdversion子模块只需声明 groupIdartifactId,自动继承版本。
版本锁定确保多模块项目中所有模块使用相同版本的依赖,避免版本碎片。是大型项目的最佳实践。
无实际依赖<dependencyManagement> 中的依赖不会被实际引入,除非在 <dependencies> 中声明。仅提供”模板”,不触发下载。
继承性子模块通过 <parent> 继承父 POM 的 dependencyManagement 配置。多级继承也适用。
BOM 导入使用 import scope 将外部 BOM 的 dependencyManagement 导入。如 Spring Boot: <scope>import</scope><type>pom</type>

父 POM 示例:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-framework-bom</artifactId>
      <version>5.3.21</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.13.3</version>
    </dependency>
  </dependencies>
</dependencyManagement>

子模块示例:

<dependencies>
  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <!-- 无需指定 version,由父 POM 管理 -->
  </dependency>
</dependencies>

5.5 查看依赖树(mvn dependency:tree

命令说明输出示例
mvn dependency:tree显示项目完整的依赖树(包括传递性依赖)。[INFO] com.example:my-app:jar:1.0-SNAPSHOT[INFO] +- junit:junit:jar:4.13.2:test[INFO] \- org.springframework:spring-core:jar:5.3.21:compile
mvn dependency:tree -Dverbose显示更详细信息,包括因冲突被忽略的依赖。会显示 (conflicts with: 2.0) 等提示。
mvn dependency:tree -Dincludes=groupId:artifactId只显示包含指定坐标的依赖。mvn dependency:tree -Dincludes=org.slf4j
mvn dependency:tree -DExcludes=commons-logging排除指定依赖,查看剩余依赖树。用于分析排除后的影响。
mvn dependency:tree > tree.txt将依赖树输出到文件。便于离线分析或分享。

使用场景:

  • 排查 ClassNotFoundExceptionNoSuchMethodError
  • 分析为何某个旧版本库被引入。
  • 优化依赖,移除不必要的传递依赖。

5.6 依赖插件常用目标

目标 (Goal)命令用途注意事项
dependency:analyzemvn dependency:analyze分析项目依赖,报告未使用的直接依赖和未声明的间接依赖。帮助清理 pom.xml,但需谨慎确认”未使用”的依赖是否真的无用。
dependency:treemvn dependency:tree显示依赖树,核心诊断工具。结合 -Dverbose 使用效果更佳。
dependency:copy-dependenciesmvn dependency:copy-dependencies将所有项目依赖复制到指定目录(默认 target/dependency)。用于创建可分发的依赖包,或离线部署。
dependency:getmvn dependency:get -Dartifact=groupId:artifactId:version手动下载单个依赖到本地仓库。调试依赖问题或预加载依赖。
dependency:sourcesmvn dependency:sources下载所有依赖的源码 JAR。便于 IDE 调试时查看第三方库源码。
dependency:resolvemvn dependency:resolve仅解析并显示项目直接依赖的坐标。快速查看有哪些直接依赖。
dependency:purge-local-repositorymvn dependency:purge-local-repository清理本地仓库中的依赖,按需重新下载。解决本地仓库损坏或强制更新 SNAPSHOT。

配置示例(在 pom.xml 中预配置 copy-dependencies):

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-dependency-plugin</artifactId>
  <executions>
    <execution>
      <id>copy-dependencies</id>
      <phase>package</phase>
      <goals>
        <goal>copy-dependencies</goal>
      </goals>
      <configuration>
        <outputDirectory>${project.build.directory}/lib</outputDirectory>
        <excludeScope>provided</excludeScope>
      </configuration>
    </execution>
  </executions>
</plugin>

此配置会在 package 阶段自动将依赖复制到 target/lib 目录。

第六章:Maven 构建生命周期与插件

6.1 三套生命周期:default、clean、site

生命周期用途独立性核心目标
default处理项目部署的核心流程,如编译、测试、打包、安装、部署。compile, test, package, install, deploy
clean清理项目,删除 target/ 目录及构建产物。clean
site生成项目文档站点,包含项目信息、报告、依赖等。site

关键特性:

  • 独立运行: 执行 mvn clean 不会触发 default 生命周期。
  • 阶段累积: 执行某个阶段时,会自动按顺序执行之前的所有阶段(如 mvn package 会依次执行 validate, compile, test, package)。
  • 无相互依赖: 三套生命周期彼此独立,但可在 pom.xml 中通过插件绑定实现跨生命周期协作。

6.2 default 生命周期阶段详解

阶段 (Phase)触发时机主要任务常见插件目标
validate构建开始验证项目是否正确,所有必要信息是否可用。-
initialize初始化初始化构建状态,如设置属性、创建目录。-
generate-sources生成源码前生成编译所需的源代码(如注解处理器、代码生成工具)。build-helper-maven-plugin:add-source
process-sources源码处理处理主源码,如资源过滤、替换占位符。maven-resources-plugin:resources
generate-resources生成资源前生成编译所需的资源文件。-
process-resources资源处理将资源文件复制到输出目录(target/classes),并进行过滤。maven-resources-plugin:resources
compile编译编译主源码到字节码(.class 文件)。maven-compiler-plugin:compile
process-classes编译后处理对编译后的字节码进行后处理,如字节码增强。maven-antrun-plugin:run, aspectj-maven-plugin:compile
generate-test-sources生成测试源码前生成测试所需的源代码。-
process-test-sources测试源码处理处理测试源码。-
generate-test-resources生成测试资源前生成测试所需的资源文件。-
process-test-resources测试资源处理将测试资源复制到测试输出目录(target/test-classes)。maven-resources-plugin:testResources
test-compile测试编译编译测试源码。maven-compiler-plugin:testCompile
process-test-classes测试编译后处理对测试编译后的字节码进行处理。-
test执行测试使用单元测试框架(如 JUnit)运行测试。maven-surefire-plugin:test
prepare-package打包准备打包前的准备工作。-
package打包将编译后的代码和资源打包成 JAR、WAR 等格式。maven-jar-plugin:jar, maven-war-plugin:war
pre-integration-test集成测试前部署包前的准备,如启动数据库、服务器。maven-antrun-plugin:run, cargo-maven2-plugin:start
integration-test执行集成测试运行集成测试。maven-failsafe-plugin:integration-test
post-integration-test集成测试后清理集成测试环境,如停止服务器。maven-antrun-plugin:run, cargo-maven2-plugin:stop
verify验证检查包是否有效,符合质量标准。maven-invoker-plugin:run, maven-failsafe-plugin:verify
install安装将包安装到本地仓库,供其他本地项目使用。maven-install-plugin:install
deploy部署将包部署到远程仓库(如 Nexus、Artifactory)。maven-deploy-plugin:deploy

说明: 每个阶段本身不执行具体任务,而是由绑定到该阶段的插件目标(Plugin Goal)来执行。

6.3 cleansite 生命周期

clean 生命周期

阶段说明插件目标
pre-clean清理前执行maven-antrun-plugin:run
clean删除 target/ 目录maven-clean-plugin:clean
post-clean清理后执行maven-antrun-plugin:run
  • 典型命令:mvn clean(删除构建产物,重新开始)。
  • 用途:确保构建环境干净,避免旧文件干扰。

site 生命周期

阶段说明插件目标
pre-site站点生成前-
site生成项目文档站点maven-site-plugin:site
post-site站点生成后-
site-deploy部署站点maven-site-plugin:deploy
  • 输出目录:target/site/
  • 生成内容:项目信息、依赖报告、测试覆盖率、代码质量报告等。
  • 典型命令:mvn site(生成站点),mvn site-deploy(部署到服务器)。

6.4 插件绑定机制

概念说明示例
默认绑定Maven 为每种 packaging 类型预定义了插件与生命周期阶段的绑定。jar 打包:compilemaven-compiler-plugin:compile / packagemaven-jar-plugin:jar
隐式绑定只要使用了某个插件,其默认目标会自动绑定到相应阶段,无需显式配置。添加 maven-compiler-plugin,其 compile 目标自动绑定到 compile 阶段。
显式绑定pom.xml 中通过 <executions> 显式配置插件目标绑定到特定阶段。maven-antrun-plugin 绑定到 pre-clean 阶段执行脚本。
覆盖默认显式配置可以覆盖默认绑定,实现自定义行为。maven-compiler-plugin 绑定到 process-sources 阶段提前编译。
多绑定一个插件目标可绑定到多个阶段,或一个阶段绑定多个插件目标。同一插件在不同阶段执行不同任务。

显式绑定配置示例:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-antrun-plugin</artifactId>
  <version>3.0.0</version>
  <executions>
    <execution>
      <id>log-start</id>
      <phase>initialize</phase>
      <goals>
        <goal>run</goal>
      </goals>
      <configuration>
        <target>
          <echo message="Build started at ${maven.build.timestamp}"/>
        </target>
      </configuration>
    </execution>
  </executions>
</plugin>

6.5 常用插件介绍(compiler、surefire、jar、war 等)

插件GroupId/ArtifactId核心目标用途配置要点
Compiler Pluginorg.apache.maven.plugins / maven-compiler-plugincompile, testCompile编译 Java 源码。设置 sourcetarget 版本(如 1.8)。
Surefire Pluginorg.apache.maven.plugins / maven-surefire-plugintest执行单元测试(src/test/java)。可配置跳过测试 (skipTests)、包含/排除测试类。
Failsafe Pluginorg.apache.maven.plugins / maven-failsafe-pluginintegration-test, verify执行集成测试(src/test/java 中的 *IT 类)。区别于 Surefire,失败时不会中断构建。
Jar Pluginorg.apache.maven.plugins / maven-jar-pluginjar将项目打包为 JAR 文件。可配置 archive(如 manifest, manifestEntries)。
War Pluginorg.apache.maven.plugins / maven-war-pluginwar将 Web 项目打包为 WAR 文件。可配置 warSourceDirectory, webXml 等。
Clean Pluginorg.apache.maven.plugins / maven-clean-pluginclean清理 target/ 目录。通常无需配置,开箱即用。
Resources Pluginorg.apache.maven.plugins / maven-resources-pluginresources, testResources复制和过滤资源文件。可配置编码、过滤规则。
Install Pluginorg.apache.maven.plugins / maven-install-plugininstall安装构件到本地仓库。-
Deploy Pluginorg.apache.maven.plugins / maven-deploy-plugindeploy部署构件到远程仓库。需在 settings.xml 配置服务器凭据。
Dependency Pluginorg.apache.maven.plugins / maven-dependency-plugincopy-dependencies, tree分析、复制、管理依赖。用于依赖树分析或打包依赖库。

6.6 自定义插件执行配置

配置项说明示例
<executions>定义插件的执行配置块,可包含多个执行。一个插件在不同阶段执行不同任务。
<execution>一个具体的执行实例,包含 id, phase, goalsid 用于标识,phase 指定生命周期阶段。
<phase>绑定到的生命周期阶段。compile, package, pre-integration-test
<goals>要执行的插件目标列表。<goal>jar</goal>, <goal>run</goal>
<configuration>插件目标的参数配置,以 XML 形式传递。设置编译版本、文件路径、开关等。
<inherited>是否被子模块继承(true/false)。通常为 true
<dependencies>为插件本身添加依赖(较少用)。为插件提供额外的库支持。

综合配置示例(自定义构建流程):

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-antrun-plugin</artifactId>
  <version>3.0.0</version>
  <executions>
    <!-- 阶段1:编译前打印信息 -->
    <execution>
      <id>pre-compile-info</id>
      <phase>compile</phase>
      <goals>
        <goal>run</goal>
      </goals>
      <configuration>
        <target>
          <echo message="Compiling project ${project.artifactId}..."/>
        </target>
      </configuration>
    </execution>
    <!-- 阶段2:打包后复制文件 -->
    <execution>
      <id>post-package-copy</id>
      <phase>package</phase>
      <goals>
        <goal>run</goal>
      </goals>
      <configuration>
        <target>
          <copy file="${project.build.directory}/${project.build.finalName}.jar"
                todir="/opt/deploy/apps/"/>
        </target>
      </configuration>
    </execution>
  </executions>
</plugin>

第七章:Maven 常用命令

7.1 项目构建相关命令

命令说明典型场景
mvn compile编译主源码(src/main/java开发阶段验证代码可编译性
mvn test-compile编译测试源码(src/test/java检查测试代码语法
mvn test编译并执行单元测试(使用 Surefire 插件)本地运行单元测试,验证功能
mvn package打包项目(如 JAR/WAR),执行 compile → test → package构建可部署的构件
mvn clean清理 target/ 目录构建前清除旧文件,确保干净环境
mvn clean compile先清理,再编译确保使用最新代码编译
mvn clean package清理、编译、测试、打包日常构建或 CI/CD 中常用
mvn install将包安装到本地仓库(~/.m2/repository供本地其他项目作为依赖使用
mvn clean install清理、编译、测试、打包、安装开发多模块项目时安装当前模块
mvn deploy部署到远程仓库(Nexus/Artifactory)发布正式版本或快照
mvn verify执行集成测试和验证CI 流水线中质量门禁检查

提示: clean 通常与其他命令组合使用,确保构建一致性。

7.2 依赖管理命令

命令说明输出示例/用途
mvn dependency:tree显示项目依赖树(含传递性依赖)查看所有依赖及其版本,分析冲突
mvn dependency:tree -Dverbose显示详细依赖树,包含冲突和被忽略的依赖排查 NoSuchMethodError 等版本冲突问题
mvn dependency:tree -Dincludes=org.slf4j只显示包含 org.slf4j 的依赖快速定位特定库的引入路径
mvn dependency:tree -DExcludes=commons-logging排除 commons-logging,查看剩余依赖分析排除后的影响
mvn dependency:analyze分析依赖使用情况报告未使用的依赖(Used undeclared)和未声明的依赖(Unused declared)
mvn dependency:copy-dependencies将所有依赖复制到 target/dependency创建可分发的依赖包
mvn dependency:sources下载所有依赖的源码便于在 IDE 中调试第三方库
mvn dependency:resolve解析并列出项目直接依赖快速查看 pom.xml 中声明的依赖

实用技巧:

  • dependency:tree 输出重定向到文件:mvn dependency:tree > deps.txt
  • 结合 grep 过滤:mvn dependency:tree | grep 'spring-core'

7.3 插件执行命令

命令说明插件目标用途
mvn compiler:compile直接调用编译插件编译主代码maven-compiler-plugin:compile跳过生命周期,直接编译
mvn surefire:test执行单元测试maven-surefire-plugin:test仅运行测试,不打包
mvn failsafe:integration-test执行集成测试maven-failsafe-plugin:integration-test运行 *IT.java 测试类
mvn failsafe:verify验证集成测试结果maven-failsafe-plugin:verify检查测试是否通过
mvn jar:jar打包 JAR 文件maven-jar-plugin:jar手动触发打包
mvn war:war打包 WAR 文件maven-war-plugin:warWeb 项目打包
mvn antrun:run执行 Ant 任务maven-antrun-plugin:run自定义构建脚本(需配置)
mvn site:site生成项目文档站点maven-site-plugin:site生成项目报告和文档
mvn versions:display-dependency-updates显示依赖的可用更新versions-maven-plugin:display-dependency-updates检查依赖是否过时(需添加插件)

注意: 直接调用插件目标时,不会自动执行生命周期的前置阶段。例如 mvn compiler:compile 不会自动执行 generate-sources

7.4 项目信息查看命令

命令说明输出内容
mvn help:effective-pom显示实际生效的 POM(合并了父 POM 和 profile)查看最终使用的配置,调试继承问题
mvn help:effective-settings显示实际生效的 Settings(合并 settings.xml查看仓库、代理、服务器等配置
mvn help:describe -Dplugin=compiler描述指定插件的信息显示插件目标、参数、默认绑定阶段
mvn help:describe -Dplugin=compiler -Dgoal=compile描述插件的特定目标查看 compiler:compile 的详细参数
mvn validate验证项目 POM 是否正确检查 pom.xml 语法和结构
mvn --versionmvn -v显示 Maven 版本、Java 版本、操作系统信息环境诊断
mvn archetype:generate创建新项目骨架交互式选择模板生成项目

调试技巧:

  • 使用 effective-pom 查看 <dependencyManagement> 是否正确继承。
  • 使用 effective-settings 确认是否使用了正确的镜像仓库。

7.5 多模块项目命令执行

场景命令说明
在根模块执行mvn clean install构建所有模块,按依赖顺序安装到本地仓库
构建指定模块mvn install -pl module-name只构建 module-name 模块
构建模块及依赖mvn install -pl module-name -am构建 module-name 及其直接依赖的模块(Aggregator Mode)
构建模块及被依赖mvn install -pl module-name -amd构建 module-name 及依赖它的模块(Also Make Dependents)
跳过测试mvn install -DskipTests安装所有模块,跳过测试执行
跳过特定模块mvn install -pl !module-to-skip排除某个模块(Maven 3.2.1+)
并行构建mvn -T 4 clean install使用 4 个线程并行构建,加速多模块项目
仅构建反应堆中的模块mvn install --also-make-am 类似,构建指定模块的依赖
查看构建顺序mvn help:reactor显示模块的构建顺序(反应堆顺序)

反应堆(Reactor): Maven 根据模块间的依赖关系计算出的构建顺序。

示例项目结构:

parent/
├── module-a (依赖 module-common)
├── module-b (依赖 module-a)
└── module-common
  • mvn install -pl module-b -am:构建顺序为 module-commonmodule-amodule-b
  • mvn install -pl module-common -amd:构建顺序为 module-commonmodule-amodule-b

第八章:仓库管理与私服

8.1 本地仓库结构解析

特性说明示例路径
默认位置用户主目录下的 .m2/repositoryC:\Users\YourName\.m2\repository (Windows) / /home/yourname/.m2/repository (Linux/macOS)
目录结构groupId 分层创建目录,artifactId 为子目录,version 为最内层com/example/my-app/1.0.0/
存储内容构件文件(JAR, WAR, POM) / 元数据文件(maven-metadata.xml) / 校验文件(.sha1, .md5my-app-1.0.0.jar / my-app-1.0.0.pom / maven-metadata-local.xml
SNAPSHOT 版本存储带时间戳和构建号的文件,便于管理快照更新my-app-1.0.0-20231001.123456-1.jar
作用缓存远程下载的依赖 / 存储本地 install 的构件 / 供多项目共享依赖避免重复下载,提升构建速度
配置方式settings.xml 中通过 <localRepository> 指定<settings><localRepository>/opt/maven/repo</localRepository></settings>

关键点:

  • 本地仓库是 Maven 构建的第一查找源。
  • 删除本地仓库中某个构件目录,可强制 Maven 重新下载(解决损坏依赖)。
  • 多用户系统中,每个用户有独立的本地仓库。

8.2 远程仓库配置(repositories

特性说明配置位置
定义指定 Maven 从哪些远程服务器下载依赖。pom.xmlsettings.xml
默认仓库Maven 默认使用中央仓库(https://repo.maven.apache.org/maven2无需配置
私有仓库企业内部仓库,存放私有构件或代理外部依赖。需手动配置
配置方式使用 <repositories><repository> 元素pom.xml 中声明
ID 唯一性每个仓库必须有唯一 id用于 settings.xml 中匹配服务器信息
布局通常为 default(Maven 2/3 标准布局)<layout>default</layout>
启用/禁用可通过 <enabled> 控制仓库是否激活默认 true

pom.xml 配置示例:

<repositories>
  <repository>
    <id>company-internal</id>
    <name>Company Internal Repository</name>
    <url>https://nexus.company.com/repository/maven-public/</url>
    <releases>
      <enabled>true</enabled>
    </releases>
    <snapshots>
      <enabled>true</enabled>
    </snapshots>
  </repository>
</repositories>

注意事项:

  • pom.xml 中配置仓库会影响所有使用该项目的构建。
  • 推荐在 settings.xml 中通过镜像统一管理,而非在 pom.xml 中硬编码。

8.3 镜像仓库配置(mirrors

特性说明配置位置
定义将对某个仓库的请求重定向到镜像仓库,实现透明代理。settings.xml
用途加速依赖下载(如使用阿里云镜像)/ 统一企业内部仓库入口 / 隔离外部网络风险提升构建效率与安全性
匹配规则通过 <mirrorOf> 指定匹配的仓库 id支持通配符
常用值*:镜像所有仓库 / central:仅镜像中央仓库 / external:*:镜像所有外部仓库灵活控制范围
身份验证镜像仓库的认证信息在 <servers> 中配置与仓库 id 对应

settings.xml 配置示例:

<settings>
  <mirrors>
    <!-- 阿里云 Maven 镜像,加速下载 -->
    <mirror>
      <id>aliyunmaven</id>
      <mirrorOf>central</mirrorOf>
      <name>Aliyun Maven</name>
      <url>https://maven.aliyun.com/repository/central</url>
    </mirror>
    <!-- 镜像所有仓库到企业 Nexus -->
    <mirror>
      <id>nexus-mirror</id>
      <mirrorOf>*</mirrorOf>
      <name>Internal Nexus Mirror</name>
      <url>https://nexus.company.com/repository/maven-all/</url>
    </mirror>
  </mirrors>
  <!-- 服务器认证信息 -->
  <servers>
    <server>
      <id>nexus-mirror</id>
      <username>deploy</username>
      <password>secret</password>
    </server>
  </servers>
</settings>

最佳实践:

  • 开发团队统一使用 settings.xml 配置镜像,避免在 pom.xml 中分散配置。
  • 使用 * 镜像时,无需在 pom.xml 中配置 repositories

8.4 私服(Nexus / Artifactory)简介

特性Nexus (Sonatype)Artifactory (JFrog)说明
类型仓库管理器通用制品仓库两者均支持 Maven、Docker、npm 等
架构Java Web 应用(War/Jar)Java 应用可部署在 Tomcat 或独立运行
核心功能代理远程仓库(Proxy)/ 存储内部构件(Hosted)/ 聚合仓库组(Group)企业级依赖管理核心-
仓库类型Proxy, Hosted, GroupLocal, Remote, Virtual实现统一访问入口
访问控制基于角色的权限管理(RBAC)细粒度权限控制控制谁可以读/写哪些仓库
高可用支持集群(Nexus Pro)原生支持集群保障生产环境稳定
UI 界面Web 管理界面功能丰富的 Web UI方便浏览和搜索构件
搜索功能支持按 GAV 搜索高级搜索(元数据、内容)快速定位依赖
社区版Nexus OSS(开源)Artifactory Community Edition免费使用,功能有限
企业版Nexus Pro(收费)Artifactory Enterprise(收费)提供高级功能(安全、审计、CI 集成)

典型部署架构:

Developer → settings.xml (Mirror) → Nexus/Artifactory

                  (Proxy) → Central Repository (Internet)
                  (Hosted) → Internal Libraries (e.g., company-utils)

所有依赖请求通过私服,私服负责缓存和分发。

8.5 部署构件到远程仓库(mvn deploy

步骤说明配置/命令
1. 配置发布仓库pom.xml 中指定 distributionManagement见下方示例
2. 配置认证信息settings.xml<servers> 中配置用户名密码见下方示例
3. 执行部署命令使用 mvn deploy 部署构件mvn clean deploy
4. 版本控制version 不含 SNAPSHOT → 发布到 repository / version 含 SNAPSHOT → 发布到 snapshotRepository自动识别
5. 部署内容主构件(JAR/WAR)、POM 文件、源码(sources)、Javadoc(javadoc)、校验文件(SHA1, MD5)可通过插件生成
6. 权限要求internal-release 仓库通常禁止重复部署相同版本 / internal-snapshot 允许覆盖防止版本污染
7. 常用参数-DskipTests:跳过测试 / -Dmaven.source.skip=true:跳过源码 / -DaltDeploymentRepository:临时指定部署仓库灵活控制部署行为

pom.xml 配置示例:

<distributionManagement>
  <repository>
    <id>internal-release</id>
    <url>https://nexus.company.com/repository/maven-releases/</url>
  </repository>
  <snapshotRepository>
    <id>internal-snapshot</id>
    <url>https://nexus.company.com/repository/maven-snapshots/</url>
  </snapshotRepository>
</distributionManagement>

settings.xml 认证配置:

<servers>
  <server>
    <id>internal-release</id>
    <username>deploy</username>
    <password>release-pass</password>
  </server>
  <server>
    <id>internal-snapshot</id>
    <username>deploy</username>
    <password>snapshot-pass</password>
  </server>
</servers>

部署流程:

  • Maven 读取 pom.xml 中的 distributionManagement
  • 根据 version 判断是 Release 还是 Snapshot。
  • 查找 settings.xml 中对应 id 的服务器凭据。
  • 将构件上传到指定仓库。

注意事项:

  • 确保 settings.xml 中的 server.idpom.xml 中的 repository.id 完全一致。
  • 部署 Release 版本前,确保代码经过充分测试。
  • 私服通常配置为拒绝 SNAPSHOT 版本进入 Release 仓库。

第九章:多模块项目管理

9.1 聚合项目(Aggregator)配置

特性说明配置方式
定义聚合项目(也称反应堆项目)用于将多个模块组织在一起,统一构建。pom.xml 中使用 <modules> 元素
核心作用统一执行构建命令(如 mvn clean install)/ 按依赖顺序自动构建模块简化多模块管理
POM 类型聚合项目的 packaging 必须为 pom<packaging>pom</packaging>
模块声明通过 <modules> 列出所有子模块的相对路径路径相对于聚合 POM
灵活性子模块可以位于任意目录层级,不要求必须在子目录中支持非标准布局
构建顺序Maven 自动计算模块间的依赖关系,确定构建顺序(反应堆顺序)无需手动指定

聚合 POM 示例(pom.xml):

<project xmlns="http://maven.apache.org/POM/4.0.0">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>my-project</artifactId>
  <version>1.0.0</version>
  <packaging>pom</packaging>
  <!-- 声明子模块 -->
  <modules>
    <module>common</module>           <!-- 子目录 common/ -->
    <module>service</module>         <!-- 子目录 service/ -->
    <module>webapp</module>          <!-- 子目录 webapp/ -->
    <module>../shared-utils</module> <!-- 上级目录的模块 -->
  </modules>
</project>

关键点:

  • 聚合是”自上而下”的,由父 POM 控制构建哪些模块。
  • 在聚合项目的根目录执行 mvn 命令,会自动应用到所有声明的模块。

9.2 继承机制(Parent POM)

特性说明配置方式
定义子模块继承父 POM 的配置,实现配置复用和统一管理。子模块中使用 <parent> 元素
核心作用统一版本管理(dependencyManagement)/ 统一插件配置 / 定义公共属性避免配置重复
POM 层级支持多级继承(Grand Parent → Parent → Child)配置可层层传递
继承内容大部分 POM 元素均可继承,包括:groupId, version / dependencies, dependencyManagement / properties / build/plugins子模块可覆盖
父 POM 位置通常与子模块在同一项目中(相对路径)或在远程仓库使用 <relativePath> 指定
强制继承子模块必须声明 <parent> 才能继承显式关系

父 POM 示例(parent/pom.xml):

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>my-parent</artifactId>
  <version>1.0.0</version>
  <packaging>pom</packaging>
  <!-- 统一依赖版本 -->
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>5.3.21</version>
      </dependency>
      <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.2</version>
        <scope>test</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>
  <!-- 统一插件配置 -->
  <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>

子模块继承示例(webapp/pom.xml):

<project>
  <modelVersion>4.0.0</modelVersion>
  <!-- 继承父 POM -->
  <parent>
    <groupId>com.example</groupId>
    <artifactId>my-parent</artifactId>
    <version>1.0.0</version>
    <relativePath>../parent/pom.xml</relativePath> <!-- 相对路径 -->
  </parent>
  <artifactId>webapp</artifactId>
  <!-- groupId 和 version 从父 POM 继承 -->
  <dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <!-- 无需指定 version,由父 POM 的 dependencyManagement 管理 -->
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <!-- scope 也从 dependencyManagement 继承 -->
    </dependency>
  </dependencies>
</project>

关键点:

  • 继承是”自下而上”的,子模块主动声明继承关系。
  • 使用 mvn help:effective-pom 可查看最终生效的完整配置。

9.3 聚合与继承的结合使用

模式说明典型结构优势
聚合与继承分离聚合 POM 和父 POM 是两个独立的项目。见下方示例灵活性高 / 父 POM 可被多个项目复用
聚合与继承合一聚合 POM 同时作为父 POM。见下方示例结构简单 / 配置集中 / 最常用模式

分离模式典型结构:

root/
├── aggregator-pom.xml  (packaging=pom, <modules>)
├── parent/
│   └── pom.xml         (packaging=pom, <dependencyManagement>)
├── module-a/
│   └── pom.xml         (<parent> 指向 parent)
└── module-b/
    └── pom.xml         (<parent> 指向 parent)

合一模式示例(root/pom.xml):

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>my-project</artifactId>
  <version>1.0.0</version>
  <packaging>pom</packaging>
  <!-- 既是聚合器,也是父 POM -->
  <modules>
    <module>common</module>
    <module>service</module>
    <module>webapp</module>
  </modules>
  <!-- 统一配置 -->
  <dependencyManagement>...</dependencyManagement>
  <build>...</build>
</project>

最佳实践:

  • 对于单一项目,推荐使用”合一”模式,简单高效。
  • 对于多个相关项目共享同一套配置,可使用”分离”模式,提高父 POM 复用性。

9.4 模块间依赖管理

场景配置方式说明注意事项
模块间依赖在子模块的 <dependencies> 中声明对其他模块的依赖。见下方示例Maven 会自动构建依赖的模块(如果在反应堆中)/ 依赖的模块必须在 dependencyManagement 中声明或版本一致
版本管理通过父 POM 的 <dependencyManagement> 统一管理所有模块的版本。见下方示例使用 ${project.version} 确保所有模块版本同步 / 避免版本碎片
循环依赖必须避免。Maven 无法构建存在循环依赖的模块。A → B → A ❌-
依赖范围可使用 testprovided 等范围控制依赖传递。如 Web 模块 provided Servlet API-
可选依赖使用 <optional>true</optional> 声明可选依赖,不传递给下游。适用于功能扩展模块-

模块间依赖声明示例(在 webapp 模块中依赖 service 模块):

<dependency>
  <groupId>com.example</groupId>
  <artifactId>service</artifactId>
  <version>1.0.0</version> <!-- 通常从父 POM 继承 -->
</dependency>

版本管理示例(在父 POM 中):

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>com.example</groupId>
      <artifactId>common</artifactId>
      <version>${project.version}</version> <!-- 使用项目版本 -->
    </dependency>
  </dependencies>
</dependencyManagement>

构建顺序: Maven 会根据依赖关系自动排序:

  • common(无内部依赖)
  • service(依赖 common
  • webapp(依赖 service

9.5 多模块构建策略

策略命令说明适用场景
全量构建mvn clean install构建所有模块,从根目录执行。初始构建、CI/CD 流水线
增量构建mvn install跳过 clean,仅重新编译变更的模块。日常开发,节省时间
并行构建mvn -T 4 clean install使用 4 个线程并行构建模块。多核机器,加速构建
聚焦构建mvn install -pl webapp仅构建 webapp 模块。只修改了某个模块
构建模块及依赖mvn install -pl webapp -am构建 webapp 及其依赖的模块(如 service, common)。修改了 webapp,需确保依赖是最新的
构建模块及被依赖mvn install -pl common -amd构建 common 及依赖它的模块(如 service, webapp)。修改了公共库,需验证所有下游
跳过测试mvn install -DskipTests安装所有模块,跳过测试执行。快速安装到本地仓库
跳过特定模块mvn install -pl !legacy-module排除 legacy-module 模块。临时跳过有问题的模块
离线构建mvn install -o仅使用本地仓库,不访问网络。无网络环境或确保稳定性
反应堆分析mvn help:reactor显示模块的构建顺序和依赖关系。调试构建流程

最佳实践:

  • 开发阶段: 使用 -pl-am/-amd 精准构建,提高效率。
  • CI/CD 环境: 使用 -T 1C(每核一线程)实现最优并行性能。
  • 发布版本: 务必执行完整测试(mvn clean deploy),避免跳过测试。
  • 依赖管理: 始终通过 dependencyManagement 统一版本,避免冲突。

第十章:Maven 高级特性

10.1 属性与资源过滤

特性说明示例
属性(Properties)定义可重用的变量,用于配置复用。<properties><app.version>1.0</app.version></properties>
内置属性Maven 预定义的属性。${basedir}(项目根目录) / ${version}(项目版本) / ${project.basedir}(同 basedir)
POM 属性引用 POM 文件中的元素。${project.groupId} / ${project.artifactId} / ${project.version}
系统属性JVM 系统属性或环境变量。${java.home} / ${env.HOME} / ${env.PATH}
自定义属性<properties> 中定义。<my.property>value</my.property>${my.property}
Settings 属性引用 settings.xml 中的值。${settings.localRepository}
资源过滤(Resource Filtering)在复制资源文件时,替换文件中的 ${} 占位符为属性值。application.properties 中的 ${db.url} 替换为实际值
启用过滤maven-resources-plugin 配置中设置 <filtering>true</filtering>见下方示例
过滤文件通过 <filters> 指定属性文件(.properties.xml)。见下方示例
典型应用多环境配置(dev/test/prod)/ 动态版本信息注入 / 构建时间戳见下方示例

启用资源过滤:

<resources>
  <resource>
    <directory>src/main/resources</directory>
    <filtering>true</filtering>
  </resource>
</resources>

指定过滤文件:

<build>
  <filters>
    <filter>config/${env}.properties</filter>
  </filters>
</build>

典型应用示例 - application.properties

app.version=${project.version}
build.time=${maven.build.timestamp}
db.url=${db.url}

构建时间戳格式: 可通过 maven.build.timestamp.format 属性自定义。

<properties>
  <maven.build.timestamp.format>yyyy-MM-dd HH:mm:ss</maven.build.timestamp.format>
</properties>

10.2 构建配置文件(Profiles)

特性说明配置位置
定义根据不同条件激活不同的构建配置。pom.xmlsettings.xml
激活方式默认激活:<activeByDefault>true</activeByDefault> / 条件激活:基于属性、JDK、操作系统、文件存在等 / 显式激活:命令行 -Pprofile-name灵活控制
配置内容可覆盖或添加:依赖、插件、属性、资源目录、模块实现差异化构建
作用域pom.xml:影响当前项目 / settings.xml:影响所有构建(全局)通常 pom.xml 更常见
ID 唯一性每个 Profile 必须有唯一 id用于命令行激活

pom.xml 中 Profile 示例:

<profiles>
  <!-- 开发环境 Profile -->
  <profile>
    <id>dev</id>
    <activation>
      <activeByDefault>true</activeByDefault>
    </activation>
    <properties>
      <env>development</env>
      <db.url>jdbc:h2:mem:testdb</db.url>
    </properties>
    <dependencies>
      <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>runtime</scope>
      </dependency>
    </dependencies>
  </profile>
  <!-- 生产环境 Profile -->
  <profile>
    <id>prod</id>
    <properties>
      <env>production</env>
      <db.url>jdbc:postgresql://prod-db:5432/app</db.url>
    </properties>
    <dependencies>
      <dependency>
        <groupId>org.postgresql</groupId>
        <artifactId>postgresql</artifactId>
      </dependency>
    </dependencies>
  </profile>
  <!-- 基于 JDK 激活 -->
  <profile>
    <id>jdk-11</id>
    <activation>
      <jdk>11</jdk>
    </activation>
    <properties>
      <maven.compiler.release>11</maven.compiler.release>
    </properties>
  </profile>
</profiles>

激活命令:

  • mvn compile -Pdev:显式激活 dev Profile
  • mvn compile:默认激活 dev(因 activeByDefault
  • mvn compile -Pprod:激活 prod Profile

最佳实践:

  • 避免在 settings.xml 中定义业务相关的 Profile。
  • 使用 Profile 实现环境隔离,而非在代码中硬编码。

10.3 多环境构建支持

方法说明实现方式
Profile + 属性过滤最常用、最灵活的方式。1. 定义多个 Profile(dev/test/prod)
2. 每个 Profile 设置不同属性(如 env
3. 资源文件使用 ${} 占位符
4. 启用资源过滤
多套资源目录为不同环境创建独立的资源目录。见下方示例
Profile 专属资源在 Profile 中覆盖资源目录。见下方示例
外部配置文件构建时指定外部属性文件。mvn install -Denv=prod,结合 <filters><filter>config-${env}.properties</filter></filters>

多套资源目录配置:

<build>
  <resources>
    <resource>
      <directory>src/main/resources-${env}</directory>
    </resource>
  </resources>
</build>

Profile 专属资源配置:

<profile>
  <id>prod</id>
  <build>
    <resources>
      <resource>
        <directory>src/main/resources-prod</directory>
      </resource>
    </resources>
  </build>
</profile>

完整示例流程:

创建配置文件:

  • src/main/filters/dev.properties:
db.url=jdbc:h2:mem:devdb
logging.level=DEBUG
  • src/main/filters/prod.properties:
db.url=jdbc:postgresql://prod-db/app
logging.level=WARN

配置 POM:

<profiles>
  <profile>
    <id>dev</id>
    <activation><activeByDefault>true</activeByDefault></activation>
    <properties><env>dev</env></properties>
  </profile>
  <profile>
    <id>prod</id>
    <properties><env>prod</env></properties>
  </profile>
</profiles>

<build>
  <filters>
    <filter>src/main/filters/${env}.properties</filter>
  </filters>
  <resources>
    <resource>
      <directory>src/main/resources</directory>
      <filtering>true</filtering>
    </resource>
  </resources>
</build>

构建命令:

  • mvn clean package → 使用 dev 配置
  • mvn clean package -Pprod → 使用 prod 配置

10.4 可重复构建与版本管理

特性说明实践方法
可重复构建(Reproducible Builds)相同的源码和依赖,在不同时间、不同机器上构建出完全相同的二进制文件。固定所有依赖版本(避免 LATEST, RELEASE)/ 使用 dependencyManagement 统一管理 / 确保构建环境一致(JDK、Maven 版本)/ 避免使用时间戳(或固定时间戳)
版本锁定确保依赖版本不因中央仓库更新而改变。使用 dependencyManagement / 使用 maven-enforcer-plugin 强制规则 / 使用 BOM(Bill of Materials)
BOM(物料清单)一种特殊的 POM,只包含 dependencyManagement,用于统一管理依赖版本。Spring Boot 的 spring-boot-dependencies
使用 BOMdependencyManagement 中导入 BOM。见下方示例
构建时间戳默认时间戳影响可重复性。设置固定时间戳或使用 SOURCE_DATE_EPOCH 环境变量
确定性构建Maven 3.6.1+ 支持更严格的可重复构建。参考 Reproducible Build Maven Plugin

BOM 导入示例:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-dependencies</artifactId>
      <version>2.7.0</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

版本管理最佳实践:

  • 主版本(1.0.0)、次版本(1.1.0)、增量版本(1.0.1)语义化。
  • SNAPSHOT 版本用于开发中,Release 版本用于生产。
  • 使用 mvn versions:set 插件批量更新版本。

10.5 使用 Maven 进行发布(mvn release:prepare 等)

阶段命令说明自动执行的操作
准备发布mvn release:prepare准备发布一个正式版本。1. 运行 cleanverify
2. 提示输入 Release 版本号(如 1.0.0)
3. 提示输入下一个开发版本号(如 1.0.1-SNAPSHOT)
4. 更新所有 pom.xml 中的版本
5. 提交更改并打 Git Tag(如 v1.0.0)
6. 提交版本更新
执行发布mvn release:perform执行发布,将构件部署到远程仓库。1. 检出 release:prepare 创建的 Tag
2. 执行 mvn deploy
3. 将 Release 构件(JAR/POM)上传到远程仓库
回滚发布mvn release:rollback如果 release:prepare 失败,回滚到之前状态。恢复 pom.xml 版本和提交
清理发布mvn release:clean清理 release 插件生成的临时文件(如 release.properties)。删除 release.properties, backup pom.xml
跳过测试mvn release:prepare -Darguments="-DskipTests"在准备阶段跳过测试。谨慎使用,仅用于快速迭代
非交互模式mvn release:prepare -B -DautoVersionSubmodules=true自动化发布(CI/CD)。-B:批处理模式 / -DautoVersionSubmodules:自动推导子模块版本

release 插件配置(pom.xml):

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-release-plugin</artifactId>
      <version>3.0.0</version>
      <configuration>
        <tagNameFormat>v@{project.version}</tagNameFormat> <!-- Tag 格式 -->
        <autoVersionSubmodules>true</autoVersionSubmodules> <!-- 自动版本 -->
        <useReleaseProfile>false</useReleaseProfile>       <!-- 不使用内置 release profile -->
        <goals>deploy</goals>                              <!-- 执行 deploy -->
      </configuration>
    </plugin>
  </plugins>
</build>

发布流程:

  • 确保代码在 main 分支,无未提交更改。
  • 执行 mvn release:prepare → 生成 v1.0.0 Tag,代码回到 1.0.1-SNAPSHOT。
  • 执行 mvn release:perform → 部署 1.0.0 版本到 Nexus。
  • (可选)执行 mvn release:clean 清理。

注意事项:

  • 发布前确保 distributionManagement 配置正确。
  • 发布的版本号不可覆盖,一旦发布失败需升级版本重试。
  • release 插件依赖 Git/SVN,确保版本控制正常。

第十一章:常见问题与最佳实践

11.1 常见错误与解决方案

错误现象可能原因解决方案
Could not resolve dependencies依赖在仓库中不存在 / 仓库 URL 配置错误 / 网络问题(代理/防火墙) / 认证失败(私服需要登录)1. 检查 pom.xml 中 groupId, artifactId, version 是否正确
2. 使用 mvn dependency:tree 查看依赖来源
3. 检查 settings.xml 中 repositories 和 mirrors 配置
4. 验证网络连接和代理设置
5. 确认 settings.xml<servers> 中有正确凭据
Plugin execution not covered by lifecycle configuration (Eclipse)IDE 未识别插件的生命周期绑定。1. 在 Eclipse 中右键项目 → Maven → Update Project
2. 或安装 m2e 连接器(m2e-connectors)
3. 在 pom.xml 中添加 <pluginManagement> 配置
Non-resolvable parent POM找不到父 POM。1. 检查 <parent> 的 groupId, artifactId, version
2. 检查 <relativePath> 是否正确(默认 ../pom.xml
3. 确保父 POM 已 install 到本地仓库或在项目结构中
Build failure: Failed to clean projecttarget/ 目录被占用(如 IDE、进程锁定)。1. 关闭占用文件的程序(如 IDE、命令行)
2. 重启 IDE 或计算机
3. 手动删除 target/ 目录
OutOfMemoryError during buildMaven 内存不足。设置环境变量:export MAVEN_OPTS="-Xms512m -Xmx2048m"
The goal you specified requires a project to execute在非项目目录执行 mvn 命令。确保在包含 pom.xml 的目录执行命令
SNAPSHOT dependency has newer version本地 SNAPSHOT 版本过期。执行 mvn clean compile -U 强制更新快照依赖

通用排查步骤:

  • 阅读错误日志:从最后一行向上查找 ERROR 或 Caused by
  • 清理重建:mvn clean compile
  • 检查配置:pom.xmlsettings.xml
  • 搜索社区:Stack Overflow、Maven 官方文档。

11.2 依赖冲突排查

方法命令/工具说明
依赖树分析mvn dependency:tree查看所有依赖及其传递路径,定位冲突来源。
详细依赖树mvn dependency:tree -Dverbose显示被忽略的依赖(因冲突被仲裁),关键诊断工具。
过滤特定依赖mvn dependency:tree -Dincludes=org.slf4j:slf4j-api快速定位 slf4j-api 的引入情况。
分析依赖使用mvn dependency:analyze报告:Used undeclared dependencies(代码使用但未声明的依赖)/ Unused declared dependencies(声明了但未使用的依赖)
查看生效 POMmvn help:effective-pom确认最终使用的 <dependencyManagement> 和依赖版本。
IDE 支持IntelliJ IDEA / Eclipse Maven 插件图形化查看依赖树,高亮冲突。

冲突解决策略:

  • 版本仲裁: Maven 默认使用”最近定义”原则(依赖树中路径最短的优先)。

  • 依赖排除: 排除传递性依赖中的冲突版本。

<dependency>
  <groupId>com.example</groupId>
  <artifactId>module-a</artifactId>
  <exclusions>
    <exclusion>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-simple</artifactId>
    </exclusion>
  </exclusions>
</dependency>
  • 依赖管理:dependencyManagement 中主动声明期望的版本。
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.36</version>
    </dependency>
  </dependencies>
</dependencyManagement>
  • 统一 BOM: 引入企业级或框架的 BOM 来管理版本。
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-dependencies</artifactId>
      <version>2.7.0</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

典型冲突场景:

  • NoSuchMethodError / ClassNotFoundException:通常是版本不匹配。
  • 日志框架混乱(SLF4J + Log4j + JUL):排除不必要的绑定。

11.3 构建性能优化

优化策略实现方式效果
并行构建mvn -T 4 clean installmvn -T 1C clean install利用多核 CPU,显著提升多模块构建速度。1C 表示每核一个线程。
跳过测试mvn install -DskipTestsmvn install -Dmaven.test.skip=true跳过测试编译和执行(后者连编译都跳过),大幅提升构建速度。
离线模式mvn install -o不访问远程仓库,仅使用本地缓存,避免网络延迟。
增量构建避免不必要的 cleanmvn compile 仅编译变更文件,比 mvn clean compile 快。
使用镜像仓库settings.xml 配置阿里云或企业 Nexus 镜像大幅加速依赖下载。
依赖预下载mvn dependency:go-offline预先下载所有依赖,确保后续构建离线可用。
配置构建环境设置 MAVEN_OPTSexport MAVEN_OPTS="-Xms512m -Xmx2g -XX:ReservedCodeCacheSize=512m" 防止 OOM。
减少依赖使用 dependency:analyze 移除未使用依赖减少传递性依赖数量,缩短依赖解析时间。
使用最新 Maven升级到 Maven 3.8+新版本在依赖解析和性能上有优化。
CI/CD 优化启用构建缓存(如 GitHub Actions, Jenkins Pipeline)/ 复用 Docker 镜像中的本地仓库避免重复下载依赖。

最佳实践:

  • 开发时: 使用 -pl-am 精准构建相关模块。
  • CI/CD: 结合并行构建、镜像仓库和构建缓存。

11.4 安全性配置(密码加密等)

安全风险解决方案配置方法
明文密码settings.xml 中的仓库密码明文存储。使用 Maven 密码加密功能。
加密主密码1. 生成主密码(Master Password)
2. 用主密码加密服务器密码
见下方示例
settings-security.xml存储加密的主密码。见下方示例
settings.xml使用加密后的密码。见下方示例
凭证管理避免在 pom.xmlsettings.xml 中硬编码凭证。使用 CI/CD 系统的 Secret 管理(如 GitHub Secrets, Jenkins Credentials)/ 构建时通过环境变量注入
依赖安全扫描使用已知漏洞的第三方库。集成 OWASP Dependency-Check 插件
最小权限原则仓库账号权限过大。为 deploy 账号仅分配 releases 仓库的写权限,snapshots 仓库的读写权限。

生成主密码:

# 生成主密码(存储在 ~/.m2/settings-security.xml)
mvn --encrypt-master-password your-master-password

settings-security.xml 示例:

<settingsSecurity>
  <master>{jSMOWnoPFgsHVpMvz5VrIt5kRbzGpI8u+44nILF95/s=}</master>
</settingsSecurity>

加密服务器密码:

# 加密服务器密码
mvn --encrypt-password your-server-password

settings.xml 使用加密密码:

<servers>
  <server>
    <id>nexus-releases</id>
    <username>deploy</username>
    <password>{jSMOWnoPFgsHVpMvz5VrIt5kRbzGpI8u+44nILF95/s=}</password>
  </server>
</servers>

OWASP Dependency-Check 插件配置:

<plugin>
  <groupId>org.owasp</groupId>
  <artifactId>dependency-check-maven</artifactId>
  <version>8.2.1</version>
  <executions>
    <execution>
      <goals><goal>check</goal></goals>
    </execution>
  </executions>
</plugin>

重要提示:

  • 主密码是解密所有服务器密码的关键,务必妥善保管。
  • 在 CI/CD 中,优先使用系统级 Secret,而非本地加密。

11.5 企业级 Maven 使用规范

规范领域推荐实践说明
目录结构遵循标准 Maven 结构src/main/java, src/test/java, src/main/resources 等,确保工具兼容性。
POM 管理统一使用企业 Parent POM 或 BOM / 禁止在 pom.xml 中使用 LATEST/RELEASE / 所有依赖通过 dependencyManagement 管理实现技术栈统一和版本可控。
版本管理使用语义化版本(SemVer)/ SNAPSHOT 用于开发,Release 用于生产 / 发布使用 maven-release-plugin确保版本清晰可追溯。
仓库策略所有项目使用企业 Nexus/Artifactory 作为镜像 / 禁止直接访问中央仓库 / 私有构件必须部署到私服集中管理,保障安全和效率。
构建流程CI/CD 流水线标准化(构建 → 测试 → 扫描 → 部署)/ 发布流程自动化 / 构建日志归档提高交付质量和可审计性。
安全性settings.xml 模板分发,密码加密 / 集成安全扫描(OWASP)/ 定期审查依赖防范供应链攻击。
文档与培训提供内部 Maven 指南 / 新员工培训降低使用门槛,保证规范落地。
工具链统一规定 Maven 版本(如 3.8.6)/ 统一 IDE 导入配置避免因环境差异导致问题。
多模块项目推荐聚合与继承合一模式 / 明确模块职责(common, service, web)/ 避免循环依赖保证项目结构清晰。
性能监控监控构建时长 / 分析慢构建原因持续优化开发体验。

企业级 settings.xml 模板示例:

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0">
  <localRepository>/opt/maven/repo</localRepository>
  <mirrors>
    <mirror>
      <id>company-nexus</id>
      <mirrorOf>*</mirrorOf>
      <url>https://nexus.company.com/repository/maven-all/</url>
    </mirror>
  </mirrors>
  <profiles>
    <profile>
      <id>company</id>
      <activation><activeByDefault>true</activeByDefault></activation>
      <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
      </properties>
    </profile>
  </profiles>
  <!-- 加密的服务器配置 -->
  <servers>
    <server>
      <id>nexus-releases</id>
      <username>${env.DEPLOY_USER}</username>
      <password>${env.DEPLOY_PASS}</password>
    </server>
  </servers>
</settings>

(在 CI/CD 中通过环境变量注入凭证)

第十二章:Maven 与 IDE 集成

12.1 IntelliJ IDEA 中使用 Maven

功能操作方式说明
项目导入File → Open → 选择 pom.xml 文件IDEA 会自动识别为 Maven 项目并导入。
Maven 工具窗口右侧边栏 Maven 标签页核心操作入口,展示项目模块、生命周期、插件、依赖。
执行生命周期在 Maven 窗口中双击 compile, test, package, install图形化执行 Maven 命令,无需记忆命令行。
执行自定义命令Maven 窗口 → 点击 Execute Maven Goal (小闪电图标) → 输入命令(如 clean compile -Pprod执行复杂或带参数的命令。
刷新项目Maven 窗口 → 点击 Reload All Maven Projects (刷新图标)pom.xml 被手动修改后,同步配置到 IDE。
依赖管理pom.xml 中编辑 <dependencies> → Reload添加/删除依赖后,IDE 会自动下载并加入类路径。
多模块项目自动识别 modules,在项目视图中分层显示可在 Maven 窗口中选择作用于单个模块或整个项目。
运行/调试右键 main 方法或测试类 → Run / Debug使用 Maven 管理的依赖和类路径。
插件集成spring-boot-maven-plugin → Maven 窗口会显示 spring-boot:run 目标可直接点击运行 Spring Boot 应用。
设置Settings → Build, Execution, Deployment → Build Tools → Maven配置 Maven home, settings.xml, 本地仓库路径。

最佳实践:

  • 保持 Maven home 与命令行 mvn -v 版本一致。
  • 使用 Reload 确保 IDE 配置与 pom.xml 同步。
  • 利用 Maven 窗口的 Dependencies 标签可视化依赖树。

12.2 Eclipse(M2Eclipse)中使用 Maven

功能操作方式说明
项目导入File → Import → Maven → Existing Maven Projects → 选择项目根目录Eclipse 的标准 Maven 导入方式。
Maven 工具窗口底部或侧边 Maven 视图(需安装 M2E 插件)显示项目、生命周期、插件等。
执行生命周期右键项目 → Run As → Maven build… → 在 Goals 输入 compile, install或使用预设的 Run As 快捷选项(如 Maven clean, Maven install)。
配置构建Run As → Maven build… → 可设置 User settings, Profiles, Goals 等创建可复用的运行配置。
更新项目右键项目 → Maven → Update Project… (快捷键 Alt+F5)关键操作:当 pom.xml 变更后,必须执行此操作同步依赖和配置。
依赖管理编辑 pom.xml → Update Project依赖会自动下载并添加到 Maven Dependencies 类路径容器。
插件错误常见错误:Plugin execution not covered by lifecycle configuration解决方案:1. Update Project / 2. 安装对应的 m2e 连接器(m2e-connectors) / 3. 在 pom.xml 中添加 <pluginManagement> 忽略配置
多模块项目自动识别聚合结构,在 Package Explorer 中以项目形式展示可对父项目或子模块单独执行 Maven 命令。
运行/调试右键 main 类 → Run As → Java Application使用 Maven 解析的依赖。

最佳实践:

  • 频繁使用 Alt+F5 (Update Project) 保持同步。
  • 遇到插件问题,优先检查是否需要安装 m2e 连接器。
  • 确保 settings.xml 配置正确(在 Preferences → Maven → User Settings 中设置)。

12.3 VS Code 中使用 Maven

功能扩展/操作方式说明
核心扩展安装 Maven for Java (由 Microsoft 提供)提供 Maven 项目支持。
项目识别打开包含 pom.xml 的文件夹扩展会自动激活并扫描 Maven 项目。
Maven 视图左侧活动栏 Maven 图标展示项目结构、生命周期、依赖、插件。
执行命令在 Maven 视图中点击生命周期目标(如 compile, package图形化执行,结果在 OUTPUT 或 TERMINAL 标签页显示。
自定义命令Maven 视图 → 点击 Execute Maven Goal → 输入命令执行复杂命令。
依赖管理编辑 pom.xml 文件保存后,扩展会提示 Import changes?,点击确认即可下载依赖。
运行/调试需配合 Extension Pack for Java安装后,可右键 main 方法 → Run / Debug。
设置settings.json (Ctrl+, → 打开设置)配置 "maven.executable.path" 指向 mvn 可执行文件。
终端集成内置终端 (`Ctrl+“)可直接运行 mvn 命令,与图形界面互补。

最佳实践:

  • 确保系统 PATH 中有 mvn,或在设置中明确指定路径。
  • 依赖更改后,留意弹出的 Import changes? 提示。
  • VS Code 的 Maven 功能相对轻量,复杂项目建议使用 IDEA 或 Eclipse。

12.4 IDE 与命令行构建一致性

问题原因解决方案
依赖不同IDE 使用的 settings.xml 或本地仓库路径与命令行不同。1. 在 IDE 设置中指定与命令行相同的 settings.xml 和 MAVEN_HOME。
2. 确认 localRepository 配置一致。
JDK 版本不同IDE 内置 JDK 与 MAVEN_OPTS 或系统 JAVA_HOME 不同。1. 在 IDE 中配置项目 SDK 为与 maven-compiler-plugin 一致的版本。
2. 检查 JAVA_HOME 环境变量。
构建结果不同IDE 增量编译,命令行 clean 后全量编译。1. IDE 构建前执行 clean 操作。
2. 命令行构建使用 mvn compile 进行增量对比。
插件行为差异IDE 未完全支持某些 Maven 插件的生命周期绑定。1. 优先以命令行构建结果为准(CI/CD 的标准)。
2. 在 IDE 中通过 Run Configuration 执行完整的 mvn clean package 命令。
Profile 未激活IDE 默认未激活某些 Profile。1. 在 IDE 的 Maven 设置中手动激活所需 Profile(如 IDEA 的 Maven → Profiles)。
2. 在 pom.xml 中设置 <activeByDefault>true</activeByDefault>
资源过滤未生效IDE 未触发资源复制和过滤。1. 在 IDE 中执行 Maven → Generate Resources 或 Process Resources。
2. 执行完整的 package 生命周期。

确保一致性的最佳实践:

  • 统一工具链: 团队内约定 Maven 版本、JDK 版本,并在文档中明确。
  • 使用 settings.xml 模板: 分发统一的 settings.xml,配置镜像仓库和服务器。
  • CI/CD 为黄金标准: 将 CI/CD 流水线(如 Jenkins, GitHub Actions)的构建结果视为最终标准。
  • 定期验证: 在本地执行 mvn clean package,并与 IDE 构建产物(如 target/ 下的 JAR)对比。
  • 文档化: 在项目 README 中写明推荐的 IDE 配置和构建命令。

终极检查:

# 在项目根目录执行
mvn clean package
# 检查 target/ 目录下的构件是否符合预期

任何 IDE 配置都应以能成功执行此命令并产生正确结果为最终目标。