首页 专题 文章 代码 归档
Maven中的POM
2020.02.21 14:22 2020.02.21 14:22

1. 什么是POM

POM( Project Object Model,项目对象模型 ) 是 Maven 工程的基本工作单元,是一个XML文件,包含了项目的基本信息,用于描述项目如何构建,声明项目依赖,等等。

在每一个Maven项目的根目录下都有一个pom.xml文件,该文件保存了项目的一些信息:

2. 基本信息

  • modelVersion:指定当前POM模型的版本,对Maven2和Maven3来说,他只能是4.0.0
  • groupId:项目的所属公司或组织的域名倒写
  • artifactId:如果该项目为一个Maven模块,则相当于项目名;如果一个项目包含多个子模块,则它们该模块的名称;(一般和项目同名)
  • version:该项目的版本信息
  • name:项目名,作用只是一个更友好的项目名称,不是必须的。
  • packaging:打包方式,默认为jar

那么一个基本的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">
    <!--指定当前POM模型的版本-->
    <modelVersion>4.0.0</modelVersion>

    <!--项目的所属公司或组织的域名倒写-->
    <groupId>com.misiai</groupId>
    <!--如果该项目为一个Maven模块,则相当于项目名;如果一个项目包含多个子模块,则它们该模块的名称;(一般和项目同名)-->
    <artifactId>test01</artifactId>
    <!--项目版本信息-->
    <version>1.0-SNAPSHOT</version>


</project>

3. 依赖管理

前面说了,使用Maven最大的一个好处,就是自动为我们管理、导入依赖。

传统的开发模式是,开发者手动下载各种jar包,然后导入到项目中,此种方式繁琐且还需要手动解决依赖冲突的问题;

那么有了工具之后,自动为我们下载依赖的jar包,管理依赖冲突。


基本结构:

<dependency>
    <groupId>...</groupId>
    <artifactId>...</artifactId>
    <version>...</version>
    <type>...</type>
    <scope>...</scope>
    <optional>...</optional>
    <exclusions>
        <exclusion>...</exclusion>
    </exclusions>
</dependency>

一般添加以来只需要groupId、artifactId、version三个标签;

  • groupId:如上groupId
  • artifactId:如上artifactId
  • version:如上version
  • type:如上packaging,默认为jar
  • scope:依赖的范围
  • optional:标记依赖是否可选
  • exclusions:用来排除一些传递性依赖

3.1. 依赖范围(scope)

  1. 首先Maven编译项目主代码时需要一套classpath
  2. 其次Maven在编译和执行测试的时候会使用另一套classpath
  3. 最后,在实际运行Maven项目的时候,又会使用一套classpath

依赖范围(scope)就是用来控制依赖以上三种classpath

编译classpath、测试classpath、运行classpath的关系,具体如下:

  • compile:编译依赖范围
    • 如果没有指定、默认为该依赖范围
    • 使用此范围,对于编译、测试、运行三种classpath都有效
  • test:测试依赖范围
    • 只对测试classpath有效
    • 在编译主代码和运行项目使用时将无法使用此类依赖
    • 比如junit
  • provided:编译及测试依赖范围
    • 对于编译及测试classpath有效,但是在运行时无效
    • 例如servlet-api,编译和测试项目时需要该依赖,但是在运行项目的时候,容器已经提供,所以不需要Maven重复引入一遍
  • runtime:运行时依赖范围
    • 对于测试和运行的classpath有效
    • 例如JDBC的驱动实现,项目主代码的编译只需要JDK提供的JDBC接口,只有在执行测试或者运行项目的时候才需要具体JDBC的实现
  • system:系统依赖范围
    • 依赖范围和provided的范围完全一致
    • 使用该范围需要使用systemPath元素显式的依赖文件的路径
    • 往往和本机绑定,可能造成构建的不可移植

截图-1582260224

3.2. 传递性依赖(exclusions)

什么是传递性依赖?

例如一个项目依赖spring-core的jar包,然后spring-core依赖commons-logging,则commons-logging为该项目的一个传递性依赖

依赖范围不仅可以控制依赖与三种classpath的关系,还对传递性依赖产生影响。

假设A依赖B,B依赖C,A对于B是第一直接依赖、B对于C是第二直接依赖、A对于C是传递性依赖


依赖调解

例如有项目A存在以下关系:A -> B -> C -> X(1.0)、A -> D -> X(2.0),X是A的传递性依赖,但是却有两个版本的X,Maven有两个原则去调解依赖重复。

  1. 路径最近者优先
  2. 第一声明者优先

最好的做法:可使用exclusions标签对一些传递性依赖进行排除

3.3. 可选依赖(optional)

假如项目A依赖项目B,项目B依赖于项目X和Y,B对于X和Y都是可选依赖:A -> B、B -> X\Y(可选),X、Y不会得以传递,称为传递性依赖。

引入这种依赖特性的原因主要是,可能项目B实现了两个特性,一个特性依赖X,一个特性依赖Y,而且这两个特性是互斥的。

4. 构建管理

常见标签如下:

<build>
    <finalName></finalName>
    <defaultGoal></defaultGoal>
    <plugins>
        <plugin></plugin>
    </plugins>
    <directory></directory>
    <resources>
        <resource></resource>
    </resources>
    <pluginManagement>
        <plugins></plugins>
    </pluginManagement>
</build>
  • finalName:构建目标文件的名称,默认情况为${artifactId}-${version}
  • defaultGoal:如果指定值package,则相当于执行命令mvn package
  • directory:构建目标文件的存放目录,默认在${basedir}/target目录中
  • plugins:插件的配置,具体的插件配置可进行查阅
  • resource:https://www.misiai.com/articles/7.html
  • pluginManagement:请看下节
本节阅读完毕! (分享
二维码图片 扫描关注我们哟