摘要:本文学习了Maven的项目级配置和全局级配置。
环境
Windows 10 企业版 LTSC 21H2
Java 1.8
Maven 3.6.0
1 总览
Maven有两个核心配置文件,作用范围与职责不同:
- pom.xml文件:存放在项目根目录,属于项目级配置文件,定义项目元信息、依赖、构建规则、配置插件等。
- settings.xml文件:存放在安装目录或用户目录,属于全局级配置文件,配置本地仓库、远程镜像、服务器认证、全局配置等。
优先级:
- 项目级pom.xml文件高于全局级settings.xml文件。
- 用户目录的settings.xml文件高于安装目录的settings.xml文件。
在某些开发工具中可以指定settings.xml配置文件的位置,指定的优先级高于用户目录和安装目录。
2 项目级配置
2.1 基础配置
模型版本与项目坐标是pom.xml文件的必选配置,用于标识项目唯一性,是依赖管理与仓库定位的基础。
2.1.1 模型版本
模型版本使用固定值4.0.0,表示遵循4.0.0版本的POM模型规范,必须放在project标签的第一行:
pom.xml1 2 3 4 5 6
| <?xml version="1.0" encoding="UTF-8"?> <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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> </project>
|
2.1.2 项目坐标
项目坐标通过GAV三要素唯一标识项目和依赖的Jar包,是Maven的核心概念:
- groupId:组织/公司标识,一般使用反向域名。
- artifactId:项目/模块标识,唯一区分同一组织的项目。
- version:版本,版本分为两种:SNAPSHOT是快照版,表示在开发中,可重复发布。RELEASE是正式版,表示稳定版,不可重复发布。
示例:
pom.xml1 2 3 4 5 6 7
| <groupId>com.example</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version>
<name>demo</name> <description>A simple demo</description>
|
使用packaging标签指定项目打包方式,默认是jar,可选值有:
- jar:普通Jar包,用于发布普通Java应用。
- war:Web应用Jar包,用于发布Web应用。
示例:
pom.xml1
| <packaging>war</packaging>
|
2.2 属性配置
Maven支持六类属性,用于统一配置、避免硬编码,使用时通过${属性名}获取对应的属性值。
2.2.1 内置属性
内置属性用于引用Maven预定义的路径和信息。
常用的内置属性:
- ${basedir}:表示项目的根目录,也就是包含pom.xml文件的目录。
- ${version}:表示项目的版本。
2.2.2 POM属性
POM属性用于引用pom.xml文件中标签的值。
常用的POM属性:
- ${project.build.sourceDirectory}:项目的主源码目录,默认是
src/main/java目录。
- ${project.build.testSourceDirectory}:项目的测试源码目录,默认是
src/test/java目录。
- ${project.build.directory}:项目构建输出目录,默认是
target目录。
- ${project.outputDirectory}:项目主代码编译输出目录,默认是
target/classes目录。
- ${project.testOutputDirectory}:项目测试代码编译输出目录,默认是
target/test-classes目录。
- ${project.groupId}:项目的groupId属性。
- ${project.artifactId}:项目的artifactId属性。
- ${project.version}:项目的version属性。
- ${project.build.finalName}:项目输出的文件名称,默认为
artifactId属性-version属性。
2.2.3 自定义属性
自定义属性用于统一管理版本。
使用properties标签表示属性,在properties标签里使用键值对的方式定义属性。
示例:
pom.xml1 2 3 4 5 6 7 8 9 10 11 12
| <properties> <junit.version>4.13.2</junit.version> </properties>
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> </dependencies>
|
2.2.4 Settings属性
Settings属性用于引用settings.xml文件中标签的值,引用时需要使用settings前缀。
示例:
- ${settings.localRepository}:获取本地仓库路径,用于自定义输出目录。
2.2.5 系统属性
系统属性用于引用系统的预定义属性。
系统属性可以通过使用mvn help:system命令查看,查询结果中的System Properties部分即为所有的系统属性。
示例:
- ${java.version}:获取Java版本。
- ${os.name}:获取操作系统名称。
2.2.6 环境变量
环境变量用于引用系统的预定义环境变量。
环境变量可以通过使用mvn help:system命令查看,查询结果中的Environment Variables部分即为所有的环境变量。
示例:
- ${env.JAVA_HOME}:获取Java安装路径。
- ${env.MAVEN_HOME}:获取Maven安装路径。
2.3 依赖管理
依赖管理是pom.xml文件的核心,用于定义项目所需的第三方Jar包,控制依赖范围和传递规则,解决依赖冲突。
2.3.1 基本结构
一个dependency标签包含多个子标签,其中GAV是必选的坐标三要素:
pom.xml1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> <exclusions> <exclusion> <groupId>org.hamcrest</groupId> <artifactId>hamcrest-core</artifactId> </exclusion> </exclusions> <optional>false</optional> </dependency> </dependencies>
|
2.3.2 依赖范围
依赖范围决定Jar包在编译、测试、运行三个阶段是否生效,能够解决依赖冗余的问题。
常见范围对比:
| 依赖范围 |
编译时期 |
测试时期 |
运行时期 |
传递规则 |
典型场景 |
示例Jar包 |
| compile |
生效 |
生效 |
生效 |
传递 |
项目主程序依赖(默认范围) |
mybatis |
| runtime |
不生效 |
生效 |
生效 |
传递 |
运行时依赖(编译仅需接口) |
mysql-connector-java |
| test |
不生效 |
生效 |
不生效 |
不传递 |
仅单元测试依赖 |
junit |
| provided |
生效 |
生效 |
不生效 |
不传递 |
容器已提供的依赖 |
servlet-api |
| system |
生效 |
生效 |
不生效 |
不传递 |
本地Jar包(不推荐) |
本地私有Jar包 |
使用system范围需通过systemPath指定本地Jar路径,其他机器如果没有这个Jar包会报错,不推荐使用system范围,私有Jar包可以通过私服管理。
2.3.3 传递规则
当A依赖B,B依赖C时,只有B依赖C使用compile范围或runtime范围才会自动传递依赖,其他依赖范围不会自动传递依赖。
在自动传递依赖的情况下,可以使用optional标签手动关闭依赖传递:
- false:开启依赖传递,默认选项。
- true:关闭依赖传递。
2.3.4 依赖冲突
由于依赖传递机制,当项目中多个Jar包依赖了同一个Jar包的不同版本时,就会导致版本冲突。
默认冲突解决机制:
- 显式声明优先:如果有直接声明的依赖版本,则覆盖传递依赖的版本。
- 路径最短优先:如果都是依赖传递的版本,路径短的版本覆盖路径长的版本。
- 声明顺序优先:如果路径长度相同,先声明的依赖版本覆盖后声明的版本。
如果默认机制不能满足开发需求,可以使用exclusions标签排除依赖冲突。
2.3.5 依赖验证
配置依赖后,可以通过mvn dependency:tree命令查看项目的依赖树,确认依赖是否正确引入,冲突是否排除。
2.4 物料清单
2.4.1 说明
当项目规模扩大时,比如多模块项目,此时通过手动同步依赖版本就容易出错,且依赖冲突风险高。
物料清单(Bill of Materials,BOM)是Maven提供的集中式版本管理工具,可将依赖版本抽离为独立配置,供所有项目复用。
BOM本质是一个特殊的POM文件,满足两个核心条件:
- 设置
packaging标签的值固定为pom,表示项目无实际代码,仅作配置声明。
- 仅包含
dependencyManagement节点,用于声明依赖版本,但不实际引入依赖。
其核心作用:
- 版本统一:所有引入BOM的项目,依赖BOM中声明的Jar包时,无需手动编写
version标签,自动继承BOM版本。
- 冲突规避:统一管理生态化依赖,避免因版本不兼容导致的冲突。
- 跨项目复用:独立于项目存在,可供公司内多个项目共享版本配置。
2.4.2 使用
创建demo-bom项目,仅需要一个pom.xml文件,不需要其他目录和文件,不需要遵循标准目录结构:
pom.xml1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| <?xml version="1.0" encoding="UTF-8"?> <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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>demo-bom</artifactId> <version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<dependencyManagement> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> </dependency> </dependencies> </dependencyManagement> </project>
|
BOM需放入仓库才能被其他项目引用,使用mvn clean install命令将BOM安装到本地仓库,也可以使用mvn clean deploy命令将BOM部署到远程仓库。
在任意项目的pom.xml文件中,通过dependencyManagement标签引入BOM,之后依赖BOM中的Jar包时,无需version标签即可引入:
pom.xml1 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
| <?xml version="1.0" encoding="UTF-8"?> <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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version>
<dependencyManagement> <dependencies> <dependency> <groupId>com.example</groupId> <artifactId>demo-bom</artifactId> <version>0.0.1-SNAPSHOT</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency> </dependencies> </project>
|
2.5 继承与聚合
当工程包含为多个模块时,通过继承统一依赖版本,通过聚合批量构建模块,避免重复配置。
2.5.1 继承
父工程通过dependencyManagement标签声明依赖版本,子工程直接引用父工程的依赖。
创建demo-bom父工程,并创建pom.xml文件,内容和BOM中的pom.xml文件相同。
在demo-bom父工程中创建demo子工程,子工程通过parent标签继承父工程:
pom.xml1 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
| <?xml version="1.0" encoding="UTF-8"?> <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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <groupId>com.example</groupId> <artifactId>demo-bom</artifactId> <version>0.0.1-SNAPSHOT</version> <relativePath>../demo-bom</relativePath> </parent>
<modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version>
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency> </dependencies> </project>
|
同引入BOM依赖不同,继承父工程时,子工程不需要使用dependencyManagement标签引入BOM依赖,但是需要使用parent标签继承父工程依赖。
2.5.2 聚合
聚合工程通过module标签管理多个子模块,执行一次命令即可批量构建所有模块,通常将父工程设计为聚合工程。
创建demo-bom聚合工程同时作为父工程,并创建pom.xml文件:
pom.xml1 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
| <?xml version="1.0" encoding="UTF-8"?> <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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>demo-bom</artifactId> <version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<modules> <module>demo</module> </modules>
<dependencyManagement> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> </dependency> </dependencies> </dependencyManagement> </project>
|
如果聚合工程不作为父工程,只需要在pom.xml文件里聚合模块:
pom.xml1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <?xml version="1.0" encoding="UTF-8"?> <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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>demo-bom</artifactId> <version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<modules> <module>demo-parent</module> <module>demo</module> </modules> </project>
|
在聚合工程根目录执行命令,会按模块依赖顺序构建所有模块。
2.6 构建配置
使用build标签配置项目的构建规则,包括处理资源文件和配置插件。
2.6.1 处理资源文件
默认将src/main/resources目录的文件复制到target/classes目录,使用resources标签可以自定义资源路径,也可以替换资源文件中的占位符。
示例:
pom.xml1 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
| <build> <resources> <resource> <directory>src/main/resources</directory> <targetPath>target/classes</targetPath> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> <resource> <directory>src/main/config</directory> <filtering>true</filtering> </resource> </resources>
<testResources> <testResource> <directory>src/test/resources</directory> <filtering>true</filtering> </testResource> </testResources> </build>
|
2.6.2 配置插件
2.6.2.1 绑定插件
Maven的生命周期阶段需绑定插件目标才能实现具体功能,使用plugin标签可以给声明周期绑定需要的插件。
在package阶段绑定maven-javadoc-plugin插件,会在执行mvn package时自动生成API文档:
pom.xml1 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-javadoc-plugin</artifactId> <version>3.5.0</version> <configuration> <encoding>UTF-8</encoding> </configuration> <executions> <execution> <id>generate-javadoc</id> <phase>package</phase> <goals> <goal>javadoc</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
|
2.6.2.2 统一插件版本
与dependencyManagement标签类似,使用pluginManagement标签也可以声明插件版本,子工程引用插件时无需写版本,避免重复配置。
父工程配置插件:
pom.xml1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <build> <pluginManagement> <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> </pluginManagement> </build>
|
子工程中引用插件:
pom.xml1 2 3 4 5 6 7 8
| <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> </plugin> </plugins> </build>
|
2.7 仓库配置
使用distributionManagement标签可以配置项目的发布仓库,包括源码和站点。
2.7.1 源码发布
源码发布主要是将项目构建生成的二进制包发布到远程仓库,根据版本类型的不同,分为发布版本和快照版本:
- 发布版本:发布版本是指功能稳定的正式版本(如
1.0.0、2.1.3),一旦发布后不允许修改或覆盖。发布版本通常用于对外发布或生产环境使用,需要存储在稳定的发布仓库中。
- 快照版本:快照版本是指不断迭代的临时版本(如
1.0.0-SNAPSHOT),用于团队内部协作时共享开发中的成果。快照版本有特殊处理机制,允许频繁更新和覆盖。
使用repository标签可以配置发布版本的仓库,使用snapshotRepository标签可以配置快照版本的仓库。
示例:
pom.xml1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <distributionManagement> <repository> <id>release-repo</id> <name>Release Repository</name> <url>https://repo.example.com/releases</url> </repository> <snapshotRepository> <id>snapshot-repo</id> <name>Snapshot Repository</name> <url>https://repo.example.com/snapshots</url> </snapshotRepository> </distributionManagement>
|
2.7.2 站点发布
站点是项目的文档集合(如API文档、使用手册、测试报告等)。
通过site标签可配置站点文档的发布仓库:
pom.xml1 2 3 4 5 6 7 8 9 10 11
| <distributionManagement> <site> <id>site-repo</id> <name>Site Repository</name> <url>http://example.com/demo/site</url> </site> </distributionManagement>
|
当项目站点迁移到新地址时,可通过relocation标签配置重定向,告知访问者新的站点位置:
pom.xml1 2 3 4 5 6 7 8 9 10 11 12
| <distributionManagement> <site> <id>site-repo</id> <name>Site Repository</name> <url>http://example.com/demo/site</url> <relocation> <id>new-site-repo</id> <name>New Site Repository</name> <url>http://example.com/demo/new-site</url> </relocation> </site> </distributionManagement>
|
2.8 多环境配置
使用profile标签可以对不同的开发环境应用不同的配置,实现多环境配置。
2.8.1 核心结构
核心结构:
pom.xml1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <profiles> <profile> <id>dev</id> <properties> <db.url>jdbc:mysql://localhost:3306/dev_db</db.url> </properties> </profile>
<profile> <id>prod</id> <properties> <db.url>jdbc:mysql://192.168.1.100:3306/prod_db</db.url> </properties> </profile> </profiles>
|
2.8.2 激活方式
支持通过多种方式激活,优先级从高到低排列:
2.8.2.1 命令行激活
使用mvn clean package -Pdev,prod通过命令行激活配置,多个用逗号分隔。
2.8.2.2 配置显示激活
在settings.xml文件中使用activeProfile标签显示激活配置:
settings.xml1 2 3 4
| <activeProfiles> <activeProfile>dev</activeProfile> <activeProfile>prod</activeProfile> </activeProfiles>
|
2.8.2.3 条件匹配激活
在pom.xml文件中使用activation标签根据配置的条件激活。
支持多种条件激活:
pom.xml1 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
| <profiles> <profile> <id>profile-env</id> <activation> <property> <name>env.ACTIVATE_PROFILE</name> <value>dev</value> </property> </activation> </profile> <profile> <id>profile-cmd</id> <activation> <property> <name>active</name> <value>dev</value> </property> </activation> </profile> <profile> <id>profile-os</id> <activation> <os> <name>windows</name> </os> </activation> </profile> <profile> <id>profile-jdk</id> <activation> <jdk>1.8</jdk> </activation> </profile> <profile> <id>profile-file</id> <activation> <file> <exists>src/main/resources/dev.properties</exists> </file> </activation> </profile> </profiles>
|
2.8.2.4 默认激活
在pom.xml文件中使用activation标签根据配置的条件激活。
没有其他激活方式时才会使用默认激活:
pom.xml1 2 3 4 5 6 7 8
| <profiles> <profile> <id>profile-default</id> <activation> <activeByDefault>true</activeByDefault> </activation> </profile> </profiles>
|
2.8.3 激活验证
执行mvn help:all-profiles命令查看所有定义的配置。
执行mvn help:active-profiles命令查看当前激活的配置,确认配置是否生效。
2 全局级配置
使用settings.xml文件控制全局行为。
3.1 配置本地仓库
使用localRepository标签指定本地仓库路径:
settings.xml1 2 3 4
| <settings> <localRepository>D:\Work\MavenRepository</localRepository> </settings>
|
3.2 配置远程镜像
国内访问中央仓库速度慢,使用mirror标签配置阿里云中央仓库镜像加速:
settings.xml1 2 3 4 5 6 7 8 9 10 11
| <settings> <mirrors> <mirror> <id>aliyunmaven</id> <mirrorOf>central</mirrorOf> <name>阿里云公共仓库</name> <url>https://maven.aliyun.com/repository/public</url> </mirror> </mirrors> </settings>
|
3.3 配置服务器认证
发布项目到远程私服时,需配置私服的账号密码:
settings.xml1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <settings> <servers> <server> <id>release-repo</id> <username>admin</username> <password>123456</password> </server> <server> <id>snapshot-repo</id> <username>admin</username> <password>123456</password> </server> </servers> </settings>
|
3.4 全局配置
使用properties标签配置全局属性:
settings.xml1 2 3
| <properties> <global.property>global-value</global.property> </properties>
|
使用profiles标签配置多环境:
settings.xml1 2 3 4 5 6 7 8 9 10 11 12 13
| <profiles> <profile> <id>jdk-8</id> <activation> <activeByDefault>true</activeByDefault> <jdk>8</jdk> </activation> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> </profile> </profiles>
|
使用activeProfile标签显示激活配置:
settings.xml1 2 3
| <activeProfiles> <activeProfile>jdk-8</activeProfile> </activeProfiles>
|
条