pom.xml 详解
POM(Project Object Model,项目对象模型)是 Maven 的核心配置文件,用来描述项目坐标、依赖、构建和发布信息。把这些写进 pom.xml,构建过程才可复现。
<?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>
<!-- The Basics -->
<groupId></groupId>
<artifactId></artifactId>
<version></version>
<packaging></packaging>
<dependencies></dependencies>
<parent></parent>
<dependencyManagement></dependencyManagement>
<modules></modules>
<properties></properties>
<!-- Build Settings -->
<build>...</build>
<reporting>...</reporting>
<!-- More Project Information -->
<name>...</name>
<description>...</description>
<url>...</url>
<inceptionYear>...</inceptionYear>
<licenses>...</licenses>
<organization>...</organization>
<developers>...</developers>
<contributors>...</contributors>
<!-- Environment Settings -->
<issueManagement>...</issueManagement>
<ciManagement>...</ciManagement>
<mailingLists>...</mailingLists>
<scm>...</scm>
<prerequisites>...</prerequisites>
<repositories>...</repositories>
<pluginRepositories>...</pluginRepositories>
<distributionManagement>...</distributionManagement>
<profiles>...</profiles>
</project>
基本配置
- project:pom.xml 中描述符的根。
- modelVersion:指定 pom.xml 符合哪个版本的描述符。Maven 2、Maven 3 只能写
4.0.0。
<?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>zhao.example</groupId>
<artifactId>java-demo</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>war</packaging>
</project>
在 Maven 中,由 groupId、artifactId、version 组成的坐标 groupId:artifactId:version 唯一识别一个构件。
- groupId:组织标识。约定用组织域名倒写,例如域名
example.zhao.com对应com.zhao.example。 - artifactId:项目在该组织下的唯一标识。注:不要在该标识符里包含点号(
.)。 - version:项目版本。常见写法是
${majorVersion}.${minorVersion}.${incrementalVersion}-${qualifier},如1.0.0-SNAPSHOT。major、minor、incremental 用数字,qualifier 用字符串。- SNAPSHOT:开发中的快照版,仓库按时间戳覆盖,不适合当正式发布号。
- LATEST、RELEASE:曾用于依赖版本解析(时间戳最新 / 最后一个非 SNAPSHOT 正式版)。Maven 3 起已不推荐,多数场景不可用,不要写进自己的
<version>。
- packaging:打包类型,默认
jar。常见:pom、jar、maven-plugin、ejb、war、ear、rar。
依赖配置
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-embedder</artifactId>
<version>2.0</version>
<type>jar</type>
<scope>test</scope>
<optional>true</optional>
<exclusions>
<exclusion>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
- groupId、artifactId、version:和基本配置中的 groupId、artifactId、version 意义相同。
- type:基本配置中的 packaging,默认为 jar。
scope:任务的类路径(编译、运行时、测试等)以及如何限制依赖关系的传递性。有 5 种限定范围:
- compile:默认范围。表示编译依赖关系在所有 classpath 中都可用。此外,这些依赖关系被传播到依赖项目。
- provided:与 compile 类似,但是表示希望 jdk 或容器在运行时提供它。它只适用于编译和测试 classpath,不可传递。
- runtime:表示编译不需要依赖关系,而是用于执行。它是在运行时和测试 classpath,但不是编译 classpath。
- test:表示正常使用应用程序不需要依赖关系,仅适用于测试编译和执行阶段。它不是传递的。
- system:与 provided 类似,但必须用
systemPath指向本地 jar,不走仓库。已不推荐,优先用私服或install:install-file。
systemPath:仅当依赖范围是 system 时才使用。否则,如果设置此元素,构建将失败。该路径必须是绝对路径,因此建议用属性指定,如:
${java.home}/lib。- optional:让其他项目知道,当使用此项目时,不需要这种依赖性也能正常工作。
- exclusions:指定一个或多个排除元素,每个元素都包含 groupId、artifactId,表示要排除的依赖项。与 optional 不同(optional 可以安装也可以不安装和使用),排除会主动地从依赖树中删除构件。如:maven-embedder 依赖于 maven-core,假设想依赖 maven-embedder,但不想在类路径中包含 maven-core 或它的依赖项。
parent
Maven 支持继承。子 POM 用 <parent> 指定父 POM,然后继承其配置。
<parent>
<groupId>zhao.example</groupId>
<artifactId>java-common</artifactId>
<version>1.0.0</version>
<relativePath></relativePath>
</parent>
- relativePath:在搜索本地和远程存储库之前,它不是必需的,但可以用作 maven 的指示符,以首先搜索给定该项目父级的路径。
dependencyManagement
dependencyManagement 是表示依赖 jar 包的声明。即使项目中的 dependencyManagement 下声明了依赖,maven 不会加载该依赖,其声明可以被子 POM 继承。
dependencyManagement 的一个使用案例是:父项目中可以利用 dependencyManagement 声明子项目中需要用到的依赖 jar 包,之后,当某个或者某几个子项目需要加载该依赖的时候,就可以在子项目中 dependencies 节点只配置 groupId 和 artifactId 就可以完成依赖的引用。
dependencyManagement 主要是为了统一管理依赖包的版本,确保所有子项目使用的版本一致。插件侧对应的是 pluginManagement。
modules
modules 标签用于声明当前 Maven 项目包含的模块子项目,每个子项目都是一个独立的 Maven 项目,具有自己的 pom.xml 文件,可以进行独立构建和测试。
<modules>
<module>project-one</module>
<module>project-two</module>
<module>project-three/pom-example.xml</module>
</modules>
properties
属性列表。定义的属性可以在 pom.xml 文件中任意处使用。使用方式为 ${属性名} 。
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
- env.X:返回 shell 的环境变量。如:
${env.PATH},表示 PATH 环境变量。虽然环境变量本身在 Windows 上不区分大小写,但 property 的查找是区分大小写的。即,Windows shell 为%PATH%和%Path%返回相同的值,但 Maven 区分了${env.PATH}和${env.Path}。 - project.x:POM 中以点号(.)表示的路径将包含相应元素的值。如:
<project><version>1.0</version></project>,可以通过${project.version}来访问。 - settings.x:settings.xml 中以点号(.)表示的路径将包含相应元素的值。如:
<settings><offline>false</offline></settings>,可通过${settings.offline}访问。 - Java 系统属性:通过 java.lang.System.getProperties() 访问的所有属性都可以作为 POM property 使用。如:
${java.home}。 - x:在 POM 中的
<properties/>元素内设置。如:<properties><someVar>value</someVar></properties>,可通过${someVar}访问。
构建配置
项目的构建配置信息,包括编译器版本、插件列表、源代码目录等。
项目的构建配置可以分为 project build 和 profile build。
<build>
<defaultGoal>install</defaultGoal>
<directory>${basedir}/target</directory>
<finalName>${artifactId}-${version}</finalName>
<filters>
<filter>filters/filter1.properties</filter>
</filters>
</build>
- defaultGoal:默认执行目标或阶段。
- directory:构建时的输出路径。默认为:
${basedir}/target。 - finalName:项目的最终构建名称(不包括文件扩展名)。
- filter:定义
*.properties文件,其中包含适用于接受其设置的资源的属性列表。换句话说,过滤器文件中定义的name=value对在资源里替换${name}字符串。
<build>
<resources>
<resource>
<targetPath>META-INF/plexus</targetPath>
<filtering>false</filtering>
<directory>${basedir}/src/main/plexus</directory>
<includes>
<include>configuration.xml</include>
</includes>
<excludes>
<exclude>**/*.properties</exclude>
</excludes>
</resource>
</resources>
<testResources></testResources>
</build>
resources
资源的配置。资源文件通常不是代码,不需要编译,而是在项目需要捆绑使用的内容。
- resources:资源元素的列表,每个资源元素描述与此项目关联的文件和何处包含文件。
- targetPath:指定从构建中放置资源集的目录结构。目标路径默认为基本目录。将要包装在 jar 中的资源的通常指定的目标路径是 META-INF。
- filtering:布尔值,表示是否要为此资源启用过滤。启用后,资源里可以用 POM 属性(如
${project.version})、命令行-Dname=value,以及<properties>里定义的值。过滤器文件里的同名键会覆盖前面这些来源。 - directory:值定义了资源的路径。默认是
${basedir}/src/main/resources。 - includes:一组文件匹配模式,指定目录中要包括的文件,使用
*作为通配符。 - excludes:与 includes 类似,指定目录中要排除的文件,使用
*作为通配符。注意:如果 include 和 exclude 发生冲突,以 exclude 作为有效项。 - testResources:与 resources 功能类似,区别仅在于 testResources 指定的资源仅用于 test 阶段,并且其默认资源目录为
${basedir}/src/test/resources。
plugins
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<extensions>false</extensions>
<inherited>true</inherited>
<configuration>
<classifier>test</classifier>
</configuration>
<dependencies></dependencies>
<executions>
<execution>
<id>echodir</id>
<goals>
<goal>run</goal>
</goals>
<phase>verify</phase>
<inherited>false</inherited>
<configuration>
<tasks>
<echo>Build Dir: ${project.build.directory}</echo>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
- groupId、artifactId、version:和基本配置中的 groupId、artifactId、version 意义相同。
- extensions:布尔值,默认为 false,表示是否加载此插件的扩展名。
- inherited:布尔值,默认为 true,表示该插件配置是否应该适用于继承自该插件的 POM。
- configuration:这是针对个人插件的配置。
- dependencies:插件本身所需要的依赖。
- executions:插件可能有多个目标,每个目标可能有一个单独的配置,甚至可能将插件的目标完全绑定到不同的阶段。执行配置插件的目标的执行。
- id:执行目标的标识。
- goals:像所有多元化的 POM 元素一样,它包含单个元素的列表。在这种情况下,这个执行块指定的插件目标列表。
- phase:这是执行目标列表的阶段。这是一个非常强大的选项,允许将任何目标绑定到构建生命周期中的任何阶段,从而改变 Maven 的默认行为。
- inherited:布尔值,false 会阻止 Maven 将这个执行传递给它的子代。此元素仅对父 POM 有意义。
- configuration:与上述相同,但将配置限制在此特定目标列表中,而不是插件下的所有目标。
pluginManagement
与 dependencyManagement 很相似,在当前 POM 中仅声明插件,而不是实际引入插件。子 POM 中只配置 groupId 和 artifactId 就可以完成插件的引用,且子 POM 有权覆盖 pluginManagement 定义。
它的目的在于统一所有子 POM 的插件版本。
directories
目录元素集合存在于 build 元素中,它为整个 POM 设置了各种目录结构。由于它们在配置文件构建中不存在,所以这些不能由配置文件更改。
<build>
<sourceDirectory>${basedir}/src/main/java</sourceDirectory>
<scriptSourceDirectory>${basedir}/src/main/scripts</scriptSourceDirectory>
<testSourceDirectory>${basedir}/src/test/java</testSourceDirectory>
<outputDirectory>${basedir}/target/classes</outputDirectory>
<testOutputDirectory>${basedir}/target/test-classes</testOutputDirectory>
</build>
如果上述目录元素的值设置为绝对路径(扩展属性时),则使用该目录。否则,它是相对于基础构建目录:${basedir}。
extensions
extensions 是在此构建中使用的 artifacts 的列表。它们将被包含在运行构建的 classpath 中。它们可以启用对构建过程的扩展,并使活动的插件能够对构建生命周期进行更改。简而言之,扩展是在构建期间激活的 artifacts
扩展不需要实际执行任何操作,也不包含 Mojo。因此,扩展对于指定普通插件接口的多个实现中的一个是非常好的。
<build>
<extensions>
<extension>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-ftp</artifactId>
<version>1.0-alpha-3</version>
</extension>
</extensions>
</build>
reporting
reporting 包含特定针对 site 生成阶段的元素。某些 Maven 插件可以生成 reporting 元素下配置的报告。
reporting 与 build 元素配置插件的能力相似。明显的区别在于:在执行块中插件目标的控制不是细粒度的,报表通过配置 reportSet 元素来精细控制。而微妙的区别在于 reporting 元素下的 configuration 元素可以用作 build 下的 configuration ,尽管相反的情况并非如此( build 下的 configuration 不影响 reporting 元素下的 configuration )。
另一个区别就是 plugin 下的 outputDirectory 元素。在报告的情况下,默认输出目录为 ${basedir}/target/site。
<reporting>
<plugins>
<plugin>
<reportSets>
<reportSet>
<id>sunlink</id>
<reports>
<report>javadoc</report>
</reports>
<inherited>true</inherited>
<configuration>
<links>
<link>https://docs.oracle.com/en/java/javase/17/docs/api/</link>
</links>
</configuration>
</reportSet>
</reportSets>
</plugin>
</plugins>
</reporting>
项目信息
项目信息相关的标签都不是必要的,其作用仅限于描述项目的详细信息。
<?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">
<name>java-demo</name>
<description>java学习</description>
<url>https://github.com/lizhao/java-demo</url>
<inceptionYear>2024</inceptionYear>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
<comments>A business-friendly OSS license</comments>
</license>
</licenses>
<organization>
<name></name>
<url></url>
</organization>
<developers>
<developer>
<id>victor</id>
<name>liZhao</name>
<email>1927344728@qq.com</email>
<url>https://github.com/lizhao</url>
<organization></organization>
<organizationUrl></organizationUrl>
<roles>
<role>architect</role>
<role>developer</role>
</roles>
<timezone>+8</timezone>
<properties></properties>
</developer>
</developers>
<contributors>
<contributor>
<!--标签内容和<developer>相同-->
</contributor>
</contributors>
</project>
环境配置
issueManagement
issueManagement 定义了所使用的缺陷跟踪系统(Bugzilla、TestTrack、ClearQuest 等)。虽然没有什么可以阻止插件使用这些信息的东西,但它主要用于生成项目文档。
<issueManagement>
<system>Bugzilla</system>
<url>http://127.0.0.1/bugzilla/</url>
</issueManagement>
ciManagement
CI 构建系统配置,用来写系统类型、地址和通知。Apache Continuum 已停更,下面只是 XML 结构示例,实际可填 Jenkins、GitHub Actions 等。
<ciManagement>
<system>continuum</system>
<url>http://127.0.0.1:8080/continuum</url>
<notifiers>
<notifier>
<type>mail</type>
<sendOnError>true</sendOnError>
<sendOnFailure>true</sendOnFailure>
<sendOnSuccess>false</sendOnSuccess>
<sendOnWarning>false</sendOnWarning>
<configuration>
<address>continuum@127.0.0.1</address>
</configuration>
</notifier>
</notifiers>
</ciManagement>
mailingLists
邮件列表。
<mailingLists>
<mailingList>
<name>lizhao</name>
<subscribe>user-subscribe@127.0.0.1</subscribe>
<unsubscribe>user-unsubscribe@127.0.0.1</unsubscribe>
<post>user@127.0.0.1</post>
<archive>http://127.0.0.1/user/</archive>
<otherArchives>
<otherArchive>http://base.google.com/base/1/127.0.0.1</otherArchive>
</otherArchives>
</mailingList>
</mailingLists>
scm
SCM(软件配置管理,也称为源代码控制或版本控制)。常见的有 SVN、Git。连接串要带 scm:git: 前缀。
<scm>
<connection>scm:git:git@github.com:lizhao/java-demo.git</connection>
<developerConnection>scm:git:ssh://git@github.com/lizhao/java-demo.git</developerConnection>
<tag>HEAD</tag>
<url>https://github.com/lizhao/java-demo</url>
</scm>
prerequisites
只对 Maven 插件项目 有意义,用来声明运行该插件所需的最低 Maven 版本。普通应用 POM 里写了也会被 Maven 3 忽略。要限制构建所用的 Maven 版本,用 maven-enforcer-plugin。
<prerequisites>
<maven>3.6.3</maven>
</prerequisites>
repositories
repositories 是遵循 Maven 存储库目录布局的 artifacts 集合。默认的 Maven 中央仓库是 https://repo.maven.apache.org/maven2/。
<repositories>
<repository>
<releases>
<enabled>false</enabled>
<updatePolicy>always</updatePolicy>
<checksumPolicy>warn</checksumPolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
<checksumPolicy>fail</checksumPolicy>
</snapshots>
<id>codehausSnapshots</id>
<name>Codehaus Snapshots</name>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
<layout>default</layout>
</repository>
</repositories>
pluginRepositories
与 repositories 差不多。
<pluginRepositories>
<pluginRepository></pluginRepository>
</pluginRepositories>
distributionManagement
distributionManagement 管理在整个构建过程中生成的 artifact 和支持文件的分布。
<distributionManagement>
<downloadUrl>https://github.com/1927344728/java-demo.git</downloadUrl>
<status>deployed</status>
</distributionManagement>
profiles
POM 可以根据构建环境切换配置。一个 profile 既包含可选的 activation(触发条件),也包含激活后要对 POM 做的一组更改。例如测试环境可以指向另一套数据库。
<profiles>
<profile>
<id>test</id>
<activation></activation>
<build></build>
<modules></modules>
<repositories></repositories>
<pluginRepositories></pluginRepositories>
<dependencies></dependencies>
<reporting></reporting>
<dependencyManagement></dependencyManagement>
<distributionManagement></distributionManagement>
</profile>
</profiles>
activation 是 profile 的关键:只在特定条件下改基础 POM,条件写在 activation 里。
<profiles>
<profile>
<id>test</id>
<activation>
<activeByDefault>false</activeByDefault>
<jdk>17</jdk>
<os>
<name>Windows XP</name>
<family>Windows</family>
<arch>x86</arch>
<version>5.1.2600</version>
</os>
<property>
<name>sparrow-type</name>
<value>African</value>
</property>
<file>
<exists>${basedir}/file2.properties</exists>
<missing>${basedir}/file1.properties</missing>
</file>
</activation>
</profile>
</profiles>