这是一份非常详细、实用、通俗易懂、权威且全面的 Maven 配置文件 (pom.xml) 全面指南。
Maven 配置文件 (pom.xml) 全面指南
目录
-
Maven 与
pom.xml简介- 1.1 什么是 Maven?
- 1.2
pom.xml的核心作用 - 1.3 项目对象模型 (POM) 概念
-
pom.xml文件结构详解- 2.1 根元素:
<project> - 2.2 基础坐标:
<groupId>,<artifactId>,<version>(GAV) - 2.3 项目元信息:
<name>,<description>,<url>,<inceptionYear>,<organization>,<licenses> - 2.4 父项目继承:
<parent> - 2.5 依赖管理:
<dependencies>和<dependency>- 2.5.1 依赖坐标 (GAV)
- 2.5.2 依赖作用域 (
<scope>) - 2.5.3 可选依赖 (
<optional>) - 2.5.4 排除传递依赖 (
<exclusions>)
- 2.6 依赖管理优化:
<dependencyManagement> - 2.7 构建配置:
<build>- 2.7.1 默认生命周期与插件
- 2.7.2 插件管理:
<pluginManagement> - 2.7.3 插件配置:
<plugins>和<plugin> - 2.7.4 资源管理:
<resources>和<resource> - 2.7.5 测试资源管理:
<testResources>和<testResource> - 2.7.6 输出目录配置 (
<directory>) - 2.7.7 最终名称 (
<finalName>)
- 2.8 报告配置:
<reporting> - 2.9 属性定义:
<properties> - 2.10 多模块项目:
<modules> - 2.11 环境配置:
<profiles>- 2.11.1 激活条件 (
<activation>) - 2.11.2 配置覆盖
- 2.11.1 激活条件 (
- 2.1 根元素:
-
pom.xml核心元素最佳实践- 3.1 GAV 命名规范
- 3.2 依赖管理策略 (
<dependencyManagement>的使用) - 3.3 插件管理策略 (
<pluginManagement>的使用) - 3.4
<scope>的合理使用 - 3.5 利用
<properties>管理公共值 - 3.6 Profile 的适用场景
-
实战案例:可直接在 IDE 中运行的系统示例
- 案例一:基础 Java 项目
- 4.1 项目描述
- 4.2
pom.xml完整代码 - 4.3 核心配置点解析
- 4.4 如何运行 (命令行 & IDE)
- 案例二:Spring Boot Web 应用
- 4.5 项目描述
- 4.6
pom.xml完整代码 - 4.7 核心配置点解析 (继承、Spring Boot 插件)
- 4.8 如何运行 (启动应用)
- 案例三:多模块项目 (Parent POM + 子模块)
- 4.9 项目结构描述
- 4.10 父模块
pom.xml完整代码 (管理依赖和插件) - 4.11 子模块 (如
core,web)pom.xml示例代码 - 4.12 核心配置点解析 (
<modules>,<parent>,<dependencyManagement>,<pluginManagement>) - 4.13 如何构建整个项目
- 案例一:基础 Java 项目
-
常见问题解答 (FAQ)
- 5.1 如何解决依赖冲突?
- 5.2 如何覆盖父 POM 中的配置?
- 5.3 如何查看项目的完整依赖树?
- 5.4 如何跳过测试 (
mvn install -DskipTests)? - 5.5
pom.xml中的变量 (${...}) 是如何解析的?
-
总结
1. Maven 与 pom.xml 简介
-
1.1 什么是 Maven? Maven 是一个强大的项目构建 和依赖管理 工具。它使用基于项目对象模型 (POM) 的概念来管理项目的构建、报告和文档。Maven 的核心思想是约定优于配置,它定义了一套标准的项目结构和构建生命周期,简化了构建过程。
-
1.2
pom.xml的核心作用pom.xml(Project Object Model) 是 Maven 项目的核心配置文件,通常位于项目的根目录下。它包含了 Maven 构建项目所需的所有信息和配置,相当于项目的"蓝图"。其主要作用包括:- 定义项目的基本信息(名称、描述、版本等)。
- 管理项目所依赖的第三方库(JAR 包)。
- 配置构建过程中使用的插件(如编译插件、测试插件、打包插件等)。
- 定义构建生命周期(
clean,compile,test,package,install,deploy等阶段)。 - 支持多模块项目的管理。
- 允许通过 Profile 进行环境特定的配置。
-
1.3 项目对象模型 (POM) 概念 POM 是一个 XML 文件,它抽象地描述了一个项目。
pom.xml就是这个模型的具体实现文件。Maven 在构建项目时,会读取pom.xml,根据其中的配置执行相应的操作。所有 Maven 项目都隐式地继承自一个超级 POM ,它包含了 Maven 的默认配置。你的pom.xml可以覆盖或扩展这些默认配置。
2. pom.xml 文件结构详解
一个完整的 pom.xml 文件遵循以下基本结构:
XML
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<!-- 模型版本 -->
<modelVersion>4.0.0</modelVersion>
<!-- 基础坐标 -->
<groupId>com.example</groupId>
<artifactId>my-project</artifactId>
<version>1.0.0-SNAPSHOT</version>
<!-- 打包类型 -->
<packaging>jar</packaging> <!-- 默认是 jar, 还有 war, pom 等 -->
<!-- 项目元信息 (可选) -->
<name>My Awesome Project</name>
<description>A project demonstrating Maven POM configuration</description>
<url>http://www.example.com/projects/my-project</url>
<inceptionYear>2023</inceptionYear>
<organization>
<name>Example Inc.</name>
<url>http://www.example.com</url>
</organization>
<licenses>
<license>
<name>The Apache License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
</license>
</licenses>
<!-- 父项目继承 (可选) -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.0</version>
<relativePath/> <!-- 通常留空,表示从本地仓库或远程仓库查找 -->
</parent>
<!-- 依赖列表 -->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 更多依赖... -->
</dependencies>
<!-- 依赖管理 (常用于父POM或BOM) -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.spring.platform</groupId>
<artifactId>spring-platform-bom</artifactId>
<version>Brussels-SR7</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 构建配置 -->
<build>
<!-- 插件列表 -->
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
<!-- 更多插件... -->
</plugins>
<!-- 插件管理 (常用于父POM) -->
<pluginManagement>
<plugins>...</plugins>
</pluginManagement>
<!-- 资源管理 -->
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering> <!-- 是否替换资源文件中的属性占位符 -->
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
<!-- 测试资源管理 -->
<testResources>...</testResources>
<!-- 输出目录配置 -->
<directory>${project.basedir}/target</directory> <!-- 默认值 -->
<outputDirectory>${project.build.directory}/classes</outputDirectory>
<testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory>
<!-- 最终打包名称 -->
<finalName>${project.artifactId}-${project.version}</finalName>
</build>
<!-- 报告配置 (主要用于生成站点文档) -->
<reporting>
<plugins>...</plugins>
</reporting>
<!-- 属性定义 -->
<properties>
<java.version>17</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>3.1.0</spring-boot.version>
</properties>
<!-- 多模块项目声明 -->
<modules>
<module>core-module</module>
<module>web-module</module>
</modules>
<!-- 环境配置 (Profiles) -->
<profiles>
<profile>
<id>development</id>
<activation>
<activeByDefault>true</activeByDefault> <!-- 默认激活 -->
</activation>
<properties>
<env>dev</env>
</properties>
</profile>
<profile>
<id>production</id>
<activation>
<property>
<name>env</name>
<value>prod</value>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests> <!-- 生产环境跳过测试 -->
</configuration>
</plugin>
</plugins>
</build>
<properties>
<env>prod</env>
</properties>
</profile>
</profiles>
</project>
下面详细解释关键部分:
-
2.1 根元素:
<project>这是整个pom.xml文件的根元素,包含了 XML 命名空间和 Schema 定义,用于验证 XML 结构。 -
2.2 基础坐标:
<groupId>,<artifactId>,<version>(GAV) 这三个元素构成了项目的唯一标识符 ,被称为 GAV 坐标。它们在 Maven 世界中至关重要。<groupId>: 通常代表组织或项目组,使用反向域名规则 (如com.example,org.apache)。它定义了项目在仓库中的路径。<artifactId>: 项目的唯一标识符。通常是项目名称 (如my-project,spring-core)。<version>: 项目的当前版本。常用格式如1.0.0,2.3.1-SNAPSHOT。SNAPSHOT表示开发中的快照版本。<packaging>: 定义项目构建后生成的主要构件类型。默认为jar。常见值:jar(Java库),war(Web应用),pom(父项目或多模块聚合),ear(企业应用)。
-
2.3 项目元信息 这些元素提供项目的描述性信息,对于生成项目文档或站点很有用。都是可选的。
<name>: 项目的人类可读名称。<description>: 项目的详细描述。<url>: 项目主页的 URL。<inceptionYear>: 项目开始的年份。<organization>: 负责项目的组织信息。<licenses>: 项目使用的许可证列表。
-
**2.4 父项目继承:
<parent>允许当前项目继承另一个项目(通常是父 POM)的配置。这是实现统一配置(如依赖版本、插件配置)的重要手段。<groupId>,<artifactId>,<version>: 父项目的 GAV 坐标。<relativePath>: 指定父pom.xml相对于当前项目的路径。通常留空<relativePath/>,表示 Maven 应先在本地仓库查找父 POM,再到远程仓库查找。如果父项目就在当前项目的父目录中(如在多模块项目中),可以设置路径如../pom.xml。
-
**2.5 依赖管理:
<dependencies>和<dependency>这是pom.xml的核心部分之一,声明项目编译、测试、运行等阶段所需的库。-
2.5.1 依赖坐标 (GAV) : 每个
<dependency>内部必须包含<groupId>,<artifactId>,<version>来指定依赖的库。如果继承了父 POM 且父 POM 的<dependencyManagement>中定义了该依赖的版本,则子 POM 可以省略<version>。 -
2.5.2 依赖作用域 (
<scope>) : 定义依赖在哪些阶段可用。非常重要!compile(默认): 编译、测试、运行时都需要。会打包到最终构件中。provided: 编译和测试时需要,但运行时由容器(如 Tomcat、JDK)提供。不会打包到最终构件中 (如servlet-api)。runtime: 不需要编译,但需要用于测试和运行。会打包到最终构件中 (如 JDBC 驱动)。test: 仅用于测试的编译和执行阶段 (如JUnit)。system: 类似于provided,但需要显式指定一个系统路径下的 JAR。不推荐使用,不利于可移植性。import: 仅用于<dependencyManagement>中的<type>pom</type>依赖,表示导入该 POM 中<dependencyManagement>的配置。
-
2.5.3 可选依赖 (
<optional>) : 设置为true表示该依赖是可选的。即使其他项目依赖于你的项目,这个可选依赖也不会被传递下去。用于解决潜在冲突。 -
2.5.4 排除传递依赖 (
<exclusions>) : 当你引入依赖 A,A 又依赖 B (传递依赖),但你不想要 B 或者 B 的版本与你的项目冲突时,可以在依赖 A 的声明中排除 B。XML<dependency> <groupId>com.example</groupId> <artifactId>library-a</artifactId> <version>1.0</version> <exclusions> <exclusion> <groupId>com.conflicting</groupId> <artifactId>library-b</artifactId> </exclusion> </exclusions> </dependency>
-
-
2.6 依赖管理优化:
<dependencyManagement>这个元素通常用于 父 POM** 或 BOM (Bill of Materials) 项目中。它本身并不引入依赖,而是声明依赖及其版本 。子项目在<dependencies>中声明依赖时,如果该依赖在父 POM 的<dependencyManagement>中定义过,就可以省略<version>(有时也可以省略<scope>),由父 POM 统一管理版本。这极大地简化了依赖版本管理,确保多模块项目中依赖版本一致。-
importscope: 用于导入另一个 POM 的<dependencyManagement>配置。XML<dependencyManagement> <dependencies> <dependency> <groupId>io.spring.platform</groupId> <artifactId>spring-platform-bom</artifactId> <version>Brussels-SR7</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
-
-
2.7 构建配置:
<build>配置项目构建过程的细节。-
2.7.1 默认生命周期与插件 : Maven 的生命周期 (
clean,default,site) 由一系列阶段 (phase) 组成。每个阶段默认绑定了一个或多个插件目标 (goal)。例如,compile阶段默认绑定maven-compiler-plugin的compile目标。 -
2.7.2 插件管理:
<pluginManagement>: 类似于<dependencyManagement>,通常用于父 POM。它声明插件及其配置,但不实际引入插件。子项目在<plugins>中声明插件时,如果父 POM 的<pluginManagement>中有定义,可以继承配置或版本。 -
2.7.3 插件配置:
<plugins>和<plugin>: 实际引入并配置项目构建所需的插件。每个<plugin>需要<groupId>,<artifactId>, 通常还有<version>。可以在<configuration>子元素中定制插件行为。XML<plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.11.0</version> <configuration> <source>17</source> <!-- Java 源代码版本 --> <target>17</target> <!-- 生成的目标 class 文件版本 --> <encoding>${project.build.sourceEncoding}</encoding> <!-- 编码 --> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <mainClass>com.example.MyApplication</mainClass> <!-- 指定启动类 --> </configuration> </plugin> </plugins> -
2.7.4 资源管理:
<resources>: 配置哪些文件从src/main/resources目录复制到输出目录 (target/classes)。可以指定<filtering>(是否替换属性占位符),<includes>,<excludes>来精细控制。 -
2.7.5 测试资源管理:
<testResources>: 类似<resources>,但针对src/test/resources目录,复制到target/test-classes。 -
2.7.6 输出目录配置 : 可以自定义输出路径(通常不建议修改默认约定)。
<directory>: 整个构建的根输出目录 (默认target)。<outputDirectory>: 主代码编译输出目录 (默认target/classes)。<testOutputDirectory>: 测试代码编译输出目录 (默认target/test-classes)。
-
2.7.7 最终名称 (
<finalName>) : 定义打包后生成的主构件的文件名(不包括扩展名)。默认是${project.artifactId}-${project.version}。例如,设置为myapp后,打包生成的 JAR 将是myapp.jar(对于jar打包类型)。
-
-
2.8 报告配置:
<reporting>配置在生成项目站点 (mvn site) 时使用的报告插件。例如 Javadoc 报告、测试报告、代码覆盖率报告等。 -
2.9 属性定义:
<properties>定义自定义属性,可以在pom.xml的其他地方通过${property.name}引用。常用于:- 定义公共版本号 (如
<spring.version>5.3.9</spring.version>)。 - 定义构建参数 (如
<java.version>17</java.version>,然后在编译器插件中引用)。 - 定义编码 (
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>)。
- 定义公共版本号 (如
-
2.10 多模块项目:
<modules>用于聚合项目 (通常打包类型为pom)。它列出了该项目包含的所有子模块。子模块通常是当前项目的子目录。Maven 命令在父项目执行时,会递归地在所有子模块上执行。XML<modules> <module>core</module> <!-- 子模块目录名 --> <module>service</module> <module>webapp</module> </modules>子模块需要通过
<parent>元素指向父项目。 -
2.11 环境配置:
<profiles>允许定义不同的构建配置集,这些配置集可以根据特定条件(环境变量、操作系统、文件是否存在等)激活。非常灵活!- 2.11.1 激活条件 (
<activation>) : 定义何时自动激活该 Profile。<activeByDefault>: 是否默认激活。<jdk>: 匹配特定 JDK 版本时激活。<os>: 匹配特定操作系统时激活。<property>: 当某个属性(系统属性或 POM 属性)存在或等于特定值时激活。<file>: 当某个文件存在或缺失时激活。
- 2.11.2 配置覆盖 : Profile 内部可以定义
<dependencies>,<dependencyManagement>,<build>,<properties>,<repositories>,<pluginRepositories>等。当 Profile 激活时,这些配置会与主 POM 的配置合并或覆盖主 POM 的配置。Profile 中的<build>配置会覆盖主 POM 的<build>配置。
XML<profiles> <profile> <id>dev</id> <activation> <property> <name>env</name> <value>dev</value> </property> </activation> <properties> <log.level>DEBUG</log.level> </properties> </profile> <profile> <id>prod</id> <activation> <property> <name>env</name> <value>prod</value> </property> </activation> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <skipTests>true</skipTests> </configuration> </plugin> </plugins> </build> <properties> <log.level>WARN</log.level> </properties> </profile> </profiles>激活 Profile 的方法:
- 命令行:
mvn clean install -P dev,prod(激活 id 为dev和prod的 Profile)。 - 命令行 (属性激活):
mvn clean install -Denv=prod。 settings.xml中配置。- IDE 通常提供界面选择激活的 Profile。
- 2.11.1 激活条件 (
3. pom.xml 核心元素最佳实践
-
3.1 GAV 命名规范
groupId: 使用组织或项目的域名反转 (e.g.,com.company,org.opensource.project)。artifactId: 简洁、有意义,通常使用小写字母和连字符 (e.g.,user-service,data-model)。version: 遵循语义化版本控制 (major.minor.patch),快照版本用SNAPSHOT后缀。避免使用final,release等非标准后缀。
-
3.2 依赖管理策略
- 优先使用
<dependencyManagement>: 尤其是在多模块项目中,父 POM 统一管理依赖版本,子模块只需声明<groupId>和<artifactId>,确保版本一致,减少冲突。 - 利用 BOM : 对于大型框架 (如 Spring Boot, Jakarta EE),使用其提供的 BOM (
<type>pom</type>,<scope>import</scope>) 来管理相关依赖的兼容版本。 - 明确指定
<scope>: 根据依赖的实际用途设置正确的 Scope,避免不必要的依赖传递和打包。 - 定期检查依赖 : 使用
mvn dependency:tree查看依赖树,mvn versions:display-dependency-updates检查可用更新。移除未使用的依赖 (mvn dependency:analyze)。
- 优先使用
-
3.3 插件管理策略
- 在父 POM 的
<pluginManagement>中统一管理常用插件的版本和基础配置。 - 在子模块的
<plugins>中引用这些插件,必要时进行覆盖或补充配置。
- 在父 POM 的
-
3.4
<scope>的合理使用- 仔细评估每个依赖的作用域。滥用
compile会导致最终包过大或冲突。正确使用provided和test能显著优化项目。
- 仔细评估每个依赖的作用域。滥用
-
3.5 利用
<properties>管理公共值- 将重复使用的值(尤其是版本号、目录路径、编码、JDK 版本)定义为属性。
- 便于统一修改和维护。
-
3.6 Profile 的适用场景
- 环境差异化配置: 开发环境 (DEBUG 日志, H2 数据库), 测试环境, 生产环境 (WARN 日志, MySQL, 跳过测试)。
- 操作系统特定配置: Windows 和 Linux 下的路径差异。
- 功能开关: 启用或禁用某些构建步骤或插件。
- 谨慎使用 : Profile 会增加配置复杂性。优先考虑通过外部配置(如
application.properties)管理运行时差异。Profile 更适合管理构建过程本身的差异。
4. 实战案例:可直接在 IDE 中运行的系统示例
案例一:基础 Java 项目
- 4.1 项目描述: 一个简单的 Java 命令行应用程序,使用 JUnit 进行测试。
- 4.2
pom.xml完整代码:
XML
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example.basic</groupId>
<artifactId>java-demo</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Basic Java Demo</name>
<description>A simple Java command-line application built with Maven.</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>11</java.version>
<junit.version>4.13.2</junit.version>
</properties>
<dependencies>
<!-- JUnit for testing -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Compiler plugin to set Java version -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<!-- Jar plugin to create executable JAR (if needed) -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<!-- If you want an executable jar, specify main class -->
<!-- <archive>
<manifest>
<mainClass>com.example.basic.App</mainClass>
</manifest>
</archive> -->
</configuration>
</plugin>
</plugins>
</build>
</project>
- 4.3 核心配置点解析 :
- 定义了 GAV 坐标。
- 使用
<properties>管理 Java 版本、编码和 JUnit 版本。 - 依赖 JUnit (
<scope>test</scope>)。 - 配置
maven-compiler-plugin指定源代码和目标字节码版本。 - 包含了
maven-jar-plugin(配置被注释,如需可执行 JAR 需取消注释并设置<mainClass>)。
- 4.4 如何运行 :
- 命令行 :
- 编译:
mvn compile - 测试:
mvn test - 打包:
mvn package(生成target/java-demo-1.0.0-SNAPSHOT.jar)
- 编译:
- IDE (如 IntelliJ IDEA, Eclipse) :
- 导入项目 (选择包含
pom.xml的文件夹)。 - Maven 配置会自动加载。
- 编写
src/main/java/com/example/basic/App.java(包含main方法)。 - 编写
src/test/java/com/example/basic/AppTest.java(JUnit 测试)。 - 右键运行
App.java或AppTest.java。使用 IDE 的 Maven 工具窗口执行 Maven 命令。
- 导入项目 (选择包含
- 命令行 :
案例二:Spring Boot Web 应用
- 4.5 项目描述: 一个使用 Spring Boot 创建的简单 RESTful Web 服务。
- 4.6
pom.xml完整代码:
XML
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- Inherit defaults from Spring Boot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.0</version> <!-- Check for latest version -->
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example.boot</groupId>
<artifactId>springboot-web-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Spring Boot Web Demo</name>
<description>Demo project for Spring Boot Web</description>
<packaging>jar</packaging> <!-- Spring Boot executable jar -->
<properties>
<java.version>17</java.version> <!-- Override parent's default if needed -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- Spring Boot Web Starter (includes embedded Tomcat, Spring MVC) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Boot Test Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Essential: Spring Boot Maven Plugin for creating executable jar/war and running -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
- 4.7 核心配置点解析 :
- 继承
spring-boot-starter-parent: 继承 Spring Boot 的默认配置(依赖管理、插件管理等)。 - 依赖
spring-boot-starter-web: 引入 Spring MVC 和嵌入式 Tomcat 等 Web 开发所需依赖。版本由父 POM 管理。 - 依赖
spring-boot-starter-test: 引入 Spring Test 和 JUnit 等测试依赖 (<scope>test</scope>)。 - 必备插件
spring-boot-maven-plugin: 这个插件是 Spring Boot 应用的核心。它负责:- 将应用打包成一个可执行的 JAR/WAR 文件(包含所有依赖和嵌入式容器)。
- 提供
spring-boot:run目标,用于在开发时快速启动应用。
- 继承
- 4.8 如何运行 :
- 命令行 :
- 运行:
mvn spring-boot:run(使用插件启动应用)。 - 打包:
mvn package(生成可执行 JARtarget/springboot-web-demo-0.0.1-SNAPSHOT.jar)。 - 运行 JAR:
java -jar target/springboot-web-demo-0.0.1-SNAPSHOT.jar.
- 运行:
- IDE :
- 导入项目。
- 找到主类 (通常带有
@SpringBootApplication注解,如src/main/java/com/example/boot/Application.java)。 - 右键运行该主类 (IDE 会识别为 Spring Boot 应用)。
- 访问
http://localhost:8080(根据你的代码定义端点)。
- 命令行 :
案例三:多模块项目 (Parent POM + 子模块)
-
4.9 项目结构描述:
parent-project/ ├── pom.xml (packaging: pom) ├── core-module/ │ ├── pom.xml │ ├── src/ │ └── ... └── web-module/ ├── pom.xml ├── src/ └── ...parent-project: 聚合项目,管理公共配置。core-module: 核心业务逻辑模块 (打包类型jar)。web-module: Web 应用模块,依赖core-module(打包类型war或jar)。
-
4.10 父模块
pom.xml完整代码 (管理依赖和插件):
XML
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example.multimodule</groupId>
<artifactId>parent-project</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging> <!-- Must be pom for aggregation -->
<name>Multi-Module Parent Project</name>
<modules>
<module>core-module</module>
<module>web-module</module>
</modules>
<!-- Dependency Management: Define versions here for child modules -->
<dependencyManagement>
<dependencies>
<!-- Define common dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>3.1.0</version> <!-- Version managed centrally -->
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<!-- Define internal module dependencies (if core-module is depended on) -->
<dependency>
<groupId>com.example.multimodule</groupId>
<artifactId>core-module</artifactId>
<version>${project.version}</version> <!-- Use project version -->
</dependency>
</dependencies>
</dependencyManagement>
<!-- Plugin Management: Define common plugin configurations -->
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<properties>
<java.version>17</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
- 4.11 子模块
core-module/pom.xml示例代码:
XML
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- Declare parent -->
<parent>
<groupId>com.example.multimodule</groupId>
<artifactId>parent-project</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <!-- Path to parent pom -->
</parent>
<artifactId>core-module</artifactId>
<packaging>jar</packaging>
<name>Core Module</name>
<dependencies>
<!-- Dependencies managed by parent's dependencyManagement -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId> <!-- Version inherited -->
<scope>test</scope>
</dependency>
<!-- Other core dependencies ... -->
</dependencies>
</project>
- 4.11 子模块
web-module/pom.xml示例代码:
XML
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example.multimodule</groupId>
<artifactId>parent-project</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>web-module</artifactId>
<packaging>war</packaging> <!-- Or jar if using embedded container -->
<name>Web Module</name>
<dependencies>
<!-- Depend on our own core module. Version managed by parent's dependencyManagement -->
<dependency>
<groupId>com.example.multimodule</groupId>
<artifactId>core-module</artifactId>
</dependency>
<!-- Spring Boot Web Starter (version managed by parent) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Boot Test Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Use plugin defined in parent's pluginManagement -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
- 4.12 核心配置点解析 :
- 父 POM (
parent-project/pom.xml) :<packaging>pom</packaging>: 声明为聚合模块。<modules>: 列出子模块core-module和web-module。<dependencyManagement>: 集中管理公共依赖 (spring-boot-starter-web,junit) 和内部模块依赖 (core-module) 的版本。子模块声明依赖时无需指定<version>。<pluginManagement>: 集中管理公共插件 (spring-boot-maven-plugin,maven-compiler-plugin) 的版本和配置。子模块可以直接引用这些插件。<properties>: 定义公共属性。
- 子模块 POM (
core-module/pom.xml,web-module/pom.xml) :<parent>: 指向父项目,继承其配置。<relativePath>指定父pom.xml的位置 (通常是../pom.xml)。<artifactId>: 定义子模块自身的标识符。<packaging>: 定义子模块的输出类型 (jar,war)。<dependencies>: 声明模块所需的依赖。对于父<dependencyManagement>中定义过的依赖,只需<groupId>和<artifactId>。web-module依赖core-module。<build>: 如果需要使用父<pluginManagement>中定义的插件,只需声明<groupId>和<artifactId>(版本和配置已继承)。可以添加模块特有的插件或覆盖配置。
- 父 POM (
- 4.13 如何构建整个项目 :
-
命令行 :
- 进入
parent-project目录 (包含父pom.xml)。 - 执行命令:
mvn clean install
- Maven 会按顺序构建所有子模块 (
core-module先于web-module,因为web-module依赖core-module)。 - 每个子模块的构建结果 (JAR/WAR) 会被安装到本地仓库 (
mvn install阶段),供其他模块或项目使用。 - 父项目本身没有代码输出。
- 进入
-
IDE :
- 导入
parent-project(包含父pom.xml的目录)。 - IDE 会自动识别为多模块项目,并加载所有子模块。
- 在父项目上右键执行 Maven 命令 (如
clean install) 会作用于所有子模块。 - 可以单独在子模块上执行命令。
- 导入
-
5. 常见问题解答 (FAQ)
-
5.1 如何解决依赖冲突?
- 使用
mvn dependency:tree查看完整的依赖关系树,找出冲突的库及其不同版本。 - 分析哪个版本是需要的。通常选择更高版本,但需注意兼容性。
- 解决方法:
- 排除传递依赖 : 在引入冲突库的依赖声明中,使用
<exclusions>排除掉不需要的传递依赖版本。 - 直接声明依赖 : 在你的
<dependencies>中显式声明你想要的依赖版本。Maven 会优先使用项目直接声明的版本 (称为"最近定义原则")。 - 使用
<dependencyManagement>: 在父 POM 或 BOM 中强制指定依赖版本。
- 排除传递依赖 : 在引入冲突库的依赖声明中,使用
- 使用
-
5.2 如何覆盖父 POM 中的配置?
- 在子模块的
pom.xml中,直接重新定义你想覆盖的元素即可。 - 例如,父 POM 定义了 Java 版本为 11 (
<java.version>11</java.version>),子模块可以定义<java.version>17</java.version>来覆盖。 - 对于插件配置,在子模块的
<plugin>声明中,重新定义<configuration>即可覆盖父 POM<pluginManagement>中的配置。
- 在子模块的
-
5.3 如何查看项目的完整依赖树?
- 命令行:
mvn dependency:tree - 这个命令会打印出项目所有依赖及其传递依赖的层次结构,是分析依赖冲突的利器。
- 可以添加
-Dverbose查看更多细节。
- 命令行:
-
5.4 如何跳过测试 (
mvn install -DskipTests)?- 命令行:
mvn clean install -DskipTests - 这会跳过测试的编译 和执行阶段。
- 如果只想跳过测试执行,但仍编译测试代码,使用
-DskipTests的变种-Dmaven.test.skip=true(通常效果相同) 或更精确的-DskipITs(跳过集成测试,如果配置了的话)。最佳实践是使用-DskipTests。
- 命令行:
-
5.5
pom.xml中的变量 (${...}) 是如何解析的?- 变量可以引用:
- 项目属性 : 如
${project.version},${project.artifactId},${project.basedir}(项目根目录)。所有定义在<properties>中的属性。所有定义在父 POM 中的属性。 - 环境变量 : 如
${env.JAVA_HOME}。 - Settings 属性 : 来自
settings.xml的属性 (如${settings.localRepository})。 - 系统属性 : Java 系统属性 (如
${user.home}),也可以通过命令行-Dproperty=value设置。
- 项目属性 : 如
- 解析顺序:通常是本地属性 -> 项目属性 -> 父项目属性 -> 系统/环境/settings 属性 -> POM 元素 (如
project.version)。具体规则可能略有不同。
- 变量可以引用: