modelVersion
指定了当前Maven模型的版本号,描述这个POM文件是遵从哪个版本的项目描述符,对于Maven2和Maven3来说,它只能是4.0.0
项目的打包类型(packing):pom、jar、war
项目中一般使用maven进行模块管理,每个模块下对应都有一个pom文件,pom文件中维护了各模块之间的依赖和继承关系。项目模块化可以将通用的部分抽离出来,方便重用;修改一部分代码不再是build整个项目,缩短了build时间;此外各模块都有自己的pom文件,结构更清晰。
使用maven进行模块划分管理,一般都会有一个父级项目,pom文件除了GAV(groupId, artifactId, version)是必须要配置的,另一个重要的属性就是packing打包类型,所有的父级项目的packing都为pom,packing默认是jar类型,如果不作配置,maven会将该项目打成jar包。作为父级项目,还有一个重要的属性,那就是modules,通过modules标签将项目的所有子项目引用进来,在build父级项目时,会根据子模块的相互依赖关系整理一个build顺序,然后依次build。
而对于各个子项目,需要在其对应的pom文件开头申明对父级项目的引用,通过GAV实现。对于子项目自己的GAV配置,GV如果不配置,则会从父级项目的配置继承过来。子模块可通过dependencies标签来添加自己的依赖,此外子类项目的packing值只能是war或者jar,前面已经说过,packing默认是jar类型。如果是需要部署的项目,则需要打包成war类型,如果只是内部调用或者是作服务使用,则推荐打包成jar类型。
optional是Maven依赖jar时的一个选项,表示该依赖是可选的,项目之间依赖不传递。不设置optional(默认)或者optional是false,表示传递依赖。
parent继承的情况
如果A的pom像下面这样配置:
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>A</groupId>
<artifactId>A</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.9.9</version>
<optional>true</optional>
</dependency>
</dependencies>
</dependencyManagement>
</project>
B再去引用的话,还是可以正常引用joda-time包,optional选项在统一控制版本的情况下会失效。
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>B</groupId>
<artifactId>B</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>A</groupId>
<artifactId>A</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
</dependencies>
</project>
在Maven项目中,恰当的使用optional配置,可以在很大程度上减少jar包的大小,提升编译和发布速度。
scope元素
scope元素主要用来控制依赖的使用范围,指定当前包的依赖范围和依赖的传递性,常见的可选值有:compile, provided, runtime, test:
compile(编译)
默认值。compile表示对应依赖会参与当前项目的编译、测试、运行等,是一个比较强的依赖。打包时通常会包含该依赖,部署时会打包到lib目录下。比如:spring-core这些核心的jar包。
test(测试)
scope为test表示依赖项目仅参与测试环节,在编译、运行、打包时不会使用。最常见的使用就是单元测试类,类似单元测试这样的依赖,如果不设置scope为test,很显然它们会被打包、发布,但其实真是环境中并无什么作用。
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>runntime(运行时)
runntime仅仅适用于运行和测试环节,在编译环境下不会被使用。比如编译时只需要JDBC API的jar,而只有运行时才需要JDBC驱动实现。
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.20</version>
<scope>runtime</scope>
</dependency>
provided(已提供)
provided适合在编译和测试的环境,和compile功能相似,但provide仅在编译和测试阶段生效,provide不会被打包,也不具有传递性。
比如:上面讲到的spring-boot-devtools、servlet-api等,前者是因为不需要在生产中热部署,后者是因为容器已经提供,不需要重复引入。
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
scope依赖的传递性
上面scope的不同参数值,针对这些参数值,在多个项目中的依赖传递性如下:
其中B依赖A,C依赖B,传递性的关键是B依赖A时所设置的scope值,当B采用不同的值时对应的依赖关系如下:当B通过test或provided依赖A时,C不依赖A;当B通过runtime或compile依赖A时,C依赖A。
<type>pom</type> 用法说明
<!-- <type>pom</type>把spring-boot-dependencies引入为pom 文件 -->
<!-- <scope>import</scope>解决单继承问题,类似parent标签,把spring-boot-dependencies引入到dependencyManagement --><dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>