Maven pom配置说明
pom介绍
POM( Project Object Model,项目对象模型 ) 是 Maven 工程的基本工作单元,是一个XML文件,包含了项目的基本信息,用于描述项目如何构建,声明项目依赖,等等。
执行任务或目标时,Maven 会在当前目录中查找 POM。它读取 POM,获取所需的配置信息,然后执行目标。
POM 中可以指定以下配置:项目依赖、插件、执行目标、项目构建 profile、项目版本、项目开发者列表、相关邮件列表信息
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>
<!-- 公司或者组织的唯一标志,并且配置时生成的路径也是由此生成, 如com.companyname.project-group,maven会将该项目打成的jar包放本地路径:/com/companyname/project-group -->
<groupId>com.companyname.project-group</groupId>
<!-- 项目的唯一ID,一个groupId下面可能多个项目,就是靠artifactId来区分的 -->
<artifactId>project</artifactId>
<!-- 版本号 -->
<version>1.0</version>
</project>
所有 POM 文件都需要 project 元素和三个必需字段:groupId,artifactId,version。
节点 | 描述 |
---|---|
project | 工程的根标签。 |
modelVersion | 模型版本需要设置为 4.0。 |
groupId | 这是工程组的标识。它在一个组织或者项目中通常是唯一的。例如,一个银行组织 com.companyname.project-group 拥有所有的和银行相关的项目。 |
artifactId | 这是工程的标识。它通常是工程的名称。例如,消费者银行。groupId 和 artifactId 一起定义了 artifact 在仓库中的位置。 |
version | 这是工程的版本号。在 artifact 的仓库中,它用来区分不同的版本。例如:com.company.bank:consumer-banking:1.0 |
pom.xml的结构说明
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>
<!-- 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>
groupId、artifactId、version三个字段上面已经提到不在过多介绍。
pom父标记集成
这里的继承概念与java中类的继承概念类似,子pom拥有父pom的所有配置, 可以通过自定义的方式覆盖/复写父pom中已经存在的配置。
举例
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
</parent>
另一种方式
<dependencyManagement>
<dependencies>
<dependency>
<!-- Import dependency management from Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.1.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
dependencies标签,依赖包维护
举例
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<type>jar</type>
<scope>test</scope>
<optional>true</optional>
</dependency>
</dependencies>
dependencies标签下声明了当前项目所使用的依赖构件。
需要注意的是,这里声明的文件必须能够在maven仓库中找到, maven默认使用中央仓库,中央仓库中包括了所有常用的开源jar包, 但对于一些闭源的三方jar包,就无法在中央仓库中找到。
因此,公司一般都会有自己的私有仓库,我们需要修改maven的settings.xml文件, 使maven使用私服处理依赖和发布。
scope标签
该标签定义了该包在哪些阶段会被放到classpath中,另外还定义了依赖的可传递性。其聚会范围如下:
classpath即类、类库加载路径,在我们的依赖中,大多数依赖会在编译、测试、运行都用到, 但也有一些依赖可能只有在编译、测试阶段运到(比如测试相关的包),还有部分包可能在编译、测试时需要, 但实际发布时不需要(比如jdk相关的包)。
值 | 含义 | 是否会将该依赖向下传递 |
---|---|---|
compile | 该值是默认值。该依赖在所有阶段的都会放入classpath中,是最常用的值。 | 是 |
provided | 只有在编译和测试时放入classpath中,实际打包时忽略该包 | 否 |
runtime | 编译时不需要,只在测试和打包时需要 | 是 |
test | 只在对测试代码做编译和执行时需要 | 否 |
system | 手动指定所依赖包的本地存在路径 | 只传递本身 |
-
compile是最常用的,一般项目引入的包在编译、测试、发布阶段都会用到。
-
provided一般用于基础包,在基础包的开发过程中会依赖一些三方包, 但可能不想为使用者带来依赖冲突的负担,此时可以使用该范围,由使用者自行决定该三方包的版本 (当然需要是兼容的版本);另一种不推荐的使用方式是将该依赖作为可选依赖向下传递, 举一个例子:我们开发了一个基础工具类包,里面含有许多工具,像poi工具、时间转换工具、中文数字工具, 另外里面还包含了TapConfigUtil用来获取配置, 此时我们注意到配置中心的集成是以springboot为基础的, 而我们想让该工具包也可以被其他类型的项目使用, 这种情况下我们可以给commons-aap-appconfig包加上provided范围。 如果某个使用者只不需要使用TapConfigUtil,那么他就不需要引入commons-aap-appconfig包。 (事实上commons-aap-appconfig包里引入spring相关的依赖里使用了provided范围)
-
runtime很少用到,一般情况下使用compile就可以了, 使用runtime甚至可能给IDE带来一些问题
-
test用在测试相关的包上,测试代码的安全性会更低(毕竟没人会写测试代码来测试测试代码 ——对外发布的测试工具除外),使用test标记测试相关的包,可以避免被其他开发人员错误的使用。
-
system需要配置systemPath标签使用,用来指定使用仓库中没有的包。 与其相比,上传私服是一种更好的方式,因为system标记的包,并不会将其依赖的包传递给使用者, 这意味着你需要自己处理好依赖关系。
exclusions标签
dependency标签下还存在exclusions标签,我们在前面讲到了依赖传递可能带来的依赖冲突问题, exclusions标签就是排除掉不想被传递过来的依赖。
这里需要注意的是,A->B->C时,如果你在引入依赖A的时候,将B排除,那么C也将被排除, 除非有其他地方也引入了C(有点像对“树”进行操作,排除进相当于直接剪掉了一个“子树”)
<exclusions>
<exclusion>
<groupId>org.objenesis</groupId>
<artifactId>objenesis</artifactId>
</exclusion>
</exclusions>
exclusion下只有groupId与artifactId两个标签,因为只不可能同时依赖一个包的不同版本。