POM(项目对象模型)是 Maven 最基本,也是非常重要的一个概念。通常情况下,我们可以看到 POM 的表现形式是pom.xml
,在这个 XML 文件中定义着关于我们工程的方方面面,当我们想要通过 Maven 命令来进行操作的时候,例如:编译,打包等等,Maven 都会从pom.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>...</groupId>
<artifactId>...</artifactId>
<version>...</version>
<packaging>...</packaging>
<dependencies>...</dependencies>
<parent>...</parent>
<dependencyManagement>...</dependencyManagement>
<modules>...</modules>
<properties>...</properties>
<!-- 项目信息配置 -->
<name>...</name>
<description>...</description>
<url>...</url>
<inceptionYear>...</inceptionYear>
<licenses>...</licenses>
<organization>...</organization>
<developers>...</developers>
<contributors>...</contributors>
<!-- 环境配置 -->
<issueManagement>...</issueManagement>
<ciManagement>...</ciManagement>
<mailingLists>...</mailingLists>
<scm>...</scm>
<prerequisites>...</prerequisites>
<repositories>...</repositories>
<pluginRepositories>...</pluginRepositories>
<distributionManagement>...</distributionManagement>
<profiles>...</profiles>
<!-- 构建配置 -->
<build>...</build>
<reporting>...</reporting>
</project>
是 pom.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">
</project>
指定pom.xml
符合哪个版本的描述符。maven 2 和 3 只能为4.0.0
。
<modelVersion>4.0.0</modelVersion>
groupId
:团体、组织的标识符。团体标识的约定是:它以创建这个项目的组织名称的逆向域名(reverse domain name)开头,一般对应着 java 的包结构。artifactId
:单独项目的唯一标识符。比如我们的 tomcat、commons 等。不要在artifactId中包含点号.
。version
:项目的特定版本,maven 在版本管理时候可以使用几个特殊的字符串SNAPSHOT、LATEST、RELEASE,例如:1.0-SNAPSHOT
SNAPSHOT
:这个版本一般用于开发过程中,表示不稳定的版本。LATEST
:指某个特定构件的最新发布,这个发布可能是一个发布版,也可能是一个snapshot版,具体看哪个时间最后。RELEASE
:指最后一个发布版。<groupId>top.ygang</groupId>
<artifactId>demo</artifactId>
<version>1.0</version>
项目的类型,描述了项目打包后的输出,默认是jar
,常见的输出类型如下:pom
、jar
、maven-plugin
、ejb
、war
、ear
、rar
、par
<packaging>jar</packaging>
指定项目的所有依赖结构
<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>
<dependency>
<groupId>top.ygang</groupId>
<artifactId>myjar</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>d:/myjar.jar</systemPath>
</dependency>
</dependencies>
dependency
:指定了单个依赖项的坐标
groupId
、artifactId
、version
:指定了依赖的坐标type
:对应 packaging
的类型,如果不使用 type
标签,maven 默认为 jar。scope
:指定了依赖的使用范围,以及依赖的传递性,共有5种可用的限定范围
compile
:如果没有指定 scope
标签,maven 默认为这个范围。编译依赖关系在所有 classpath 中都可用。此外,这些依赖关系被传播到依赖项目。provided
:与 compile 类似,但是表示您希望 jdk 或容器在运行时提供它。它只适用于编译和测试 classpath,不可传递。runtime
:表示编译不需要依赖关系,而是用于执行。它是在运行时和测试 classpath,但不是编译 classpath。test
:此范围表示正常使用应用程序不需要依赖关系,仅适用于测试编译和执行阶段。它不是传递的。system
:此范围与 provided 类似,除了您必须提供明确包含它的 jar。该artifact 始终可用,并且不是在仓库中查找。systemPath
:仅当scope
为system
才使用。否则,如果设置此元素,构建将失败。该路径必须是绝对路径,因此建议使用 propertie
来指定特定的路径。maven 将不会检查项目的仓库,而是检查库文件是否存在。如果没有,maven 将会失败。optional
:设置此依赖项为可选,如果子项目存在该依赖项,则不会传递该依赖给子项目,避免了依赖冲突exclusions
:指定一个或多个排除需要排除的传递而来的依赖,每个排除依赖都包含 groupId
和 artifactId
。maven 支持继承功能。子 POM 可以使用 parent
指定父 POM ,然后继承其配置。
<parent>
<groupId>top.ygang</groupId>
<artifactId>my-parent</artifactId>
<version>2.0</version>
<relativePath>../my-parent</relativePath>
</parent>
relativePath
:在搜索本地和远程存储库之前,它不是必需的,但可以用作 maven 的指示符,优先搜索给定该项目父级的路径。<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-embedder</artifactId>
<version>2.0</version>
</dependency>
</dependencies>
</dependencyManagement>
表示依赖 jar 包的声明。即你在项目中的 dependencyManagement
下声明了依赖,maven 不会加载该依赖,dependencyManagement
声明可以被子 POM 继承。
常见的使用方式为,父项目声明<packaging>pom</packaging>
,并且使用dependencyManagement
来指定依赖以及版本;子项目只需要使用groupId
和 artifactId
来指定依赖,而依赖版本会继承父项目指定的版本。
dependencyManagement
主要是为了统一管理依赖包的版本,确保所有子项目使用的版本一致,类似的还有plugins
和pluginManagement
。
dependencyManagement
中可以写一个特殊的scope
:<scope>import</scope>
,作用是如果当前的<parent>
继承一个不够,那么可以使用这个标签在dependencyManagement
继承多个。
属性列表。定义的属性可以在pom.xml
文件中任意处使用。使用方式为 ${propertie}
。
<!-- 常用属性 -->
<properties>
<!-- 指定maven构建项目时使用的编码,防止乱码 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- 编译代码使用的jdk版本 -->
<maven.compiler.source>8</maven.compiler.source>
<!-- 运行代码使用的jdk版本 -->
<maven.compiler.target>8</maven.compiler.target>
</properties>
内置属性
${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
,与${version}
等价
${project.build.fianlName}
:项目打包输出文件的名称。默认为${project.artifactId}-${project.version}
${project.basedir}
:pom.xml
所在的目录,与${basedir}
等价
项目信息相关的这部分标签都不是必要的,也就是说完全可以不填写。
<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>maven-demo</name>
<!--项目描述-->
<description>maven示例</description>
<!--项目url-->
<url>https://github.com/gradyyoung/maven-demo</url>
<!--项目开发年份-->
<inceptionYear>2019</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>1</id>
<name>ygang1</name>
<email>example@email.com</email>
<url>https://www.ygang.top/</url>
<organization>...</organization>
<organizationUrl>...</organizationUrl>
<roles>
<role>architect</role>
<role>developer</role>
</roles>
<timezone>+8</timezone>
<properties>...</properties>
</developer>
</developers>
<!--代码贡献者列表-->
<contributors>
<contributor>
<id>1</id>
<name>ygang2</name>
<email>example@email.com</email>
<url>https://www.ygang.top/</url>
<organization>...</organization>
<organizationUrl>...</organizationUrl>
<roles>
<role>architect</role>
<role>developer</role>
</roles>
<timezone>+8</timezone>
<properties>...</properties>
</contributor>
</contributors>
</project>
这定义了所使用的缺陷跟踪系统(Bugzilla,TestTrack,ClearQuest 等)。虽然没有什么可以阻止插件使用这些信息的东西,但它主要用于生成项目文档。
<issueManagement>
<system>Bugzilla</system>
<url>http://127.0.0.1/bugzilla/</url>
</issueManagement>
CI 构建系统配置,主要是指定通知机制以及被通知的邮箱。
<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>
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>http://snapshots.maven.codehaus.org/maven2</url>
<layout>default</layout>
</repository>
</repositories>
与 repositories
差不多。
和settings.xml
中的profiles作用一样,但是子标签除了id
、activation
、repositories
、pluginRepositories
和 properties
这几个基本的以外,还有类似于dependencies
,build
等pom.xml
标签,可以更加全面的分类配置项目。
<profiles>
<profile>
<id>p1</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.31</version>
</dependency>
</dependencies>
</profile>
<profile>
<id>p2</id>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
</dependencies>
</profile>
</profiles>
<activeByDefault>true</activeByDefault>
激活,优先级最低,一旦使用方式二三,则此方式失效mvn [command] -P profileId
激活,例如mvn package -P p2
activation
标签中的各种条件激活项目的构建配置
<build>
<defaultGoal>install</defaultGoal>
<directory>${basedir}/target</directory>
<finalName>${artifactId}-${version}</finalName>
<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>
<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>...</executions>
</plugin>
</plugins>
</build>
defaultGoal
:执行构建时默认的goal或phase,如jar:jar
或者package
等directory
:构建的结果所在的路径,默认为${basedir}/target
目录finalName
:构建的最终结果的名字,默认为${artifactId}-${version}
,该名字可能在其他plugin中被改变resources
:资源的配置。资源文件通常不是代码,不需要编译,而是在项目需要捆绑使用的内容。
targetPath
: 指定从构建中放置资源集的目录结构。目标路径默认为基本目录。将要包装在jar中的资源的通常指定的目标路径是META-INF
。filtering
:构建过程中是否对资源进行过滤,默认falsedirectory
:资源文件的路径,默认位于${basedir}/src/main/resources/
目录下includes
:一组文件名的匹配模式,被匹配的资源文件将被构建过程处理excludes
:一组文件名的匹配模式,被匹配的资源文件将被构建过程忽略。同时被includes
和excludes
匹配的资源文件,将被忽略。plugins
:构建过程中所用到的插件
groupId
、artifactId
、version
:和基本配置中的 groupId
、artifactId
、version
意义相同。extensions
:是否加载该插件的扩展,默认falseinherited
:该插件的configuration中的配置是否可以被继承,默认trueconfiguration
:该插件所需要的特殊配置,在父子项目之间可以覆盖或合并dependencies
:插件本身所需要的依赖executions
:该插件的某个goal(一个插件中可能包含多个goal)的执行方式。
id
:唯一标识goals
:要执行的插件的goal
(可以有多个),如<goal>run</goal>
phase
:插件的goal
要嵌入到Maven的phase中执行,如verify
inherited
:该execution是否可被子项目继承configuration
:该execution的其他配置参数包含特定针对 site
生成阶段的元素。某些 maven 插件可以生成 reporting
元素下配置的报告,例如:生成 javadoc 报告。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>http://java.sun.com/j2se/1.5.0/docs/api/</link>
</links>
</configuration>
</reportSet>
</reportSets>
</plugin>
</plugins>
</reporting>