• Maven POM文件介绍



    本文链接: https://www.cnblogs.com/hchengmx/p/15085639.html

    1. POM文件是什么

    pom是 Project Object Module(项目对象模型)的缩写,是Maven中的项目文件。这个文件很多 默认值。

    官方网站 参考,目前Maven最新版本为 3.8.1

    1.1 Super POM

    Super POM 是一个特殊的POM文件,也是 Maven默认的 POM。

    要是不指定的话,所有的 POM 都是继承于 Super POM,要是修改了 setting.xml文件,就会 读取xml文件中的配置。

    这个POM文件可以在 [Maven Super Pom](Maven Model Builder – Super POM) 找到。

    也可以在 本地这个路径找到 $MAVEN_HOME/lib/maven-model-builder-3.8.1.jar!/org/apache/maven/model/pom-4.0.0.xml

    注:必须解压 maven-model-builder-3.8.1.jar 这个文件后,才可以得到得到进一步的路径。

    以3.8.1 为例,Super POM 里面主要定义了一些基本的配置,

    1. repositories

    定义了一个名叫 central的repository,value是 'https://repo.maven.apache.org/maven2',可以从这个地址拉下来dependency。

    2. pluginRepositories

    默认 plugin的 repositories

    3. build

    设置了一些默认的路径,其中还定义了 几个插件,不过Maven官方也提醒,未来的版本会去掉。

    <pluginManagement>
        <!-- NOTE: These plugins will be removed from future versions of the super POM -->
        <!-- They are kept for the moment as they are very unlikely to conflict with lifecycle mappings (MNG-4453) -->
        .....
    </pluginManagement>
    

    1.2 Minimal POM

    对于一个POM来说,至少需要以下几个标签

    • project:root
    • modelVersion: 4.0.0
    • groupId: project所在组
    • artifactId: artifact(project)的id
    • version: artifact的版本

    e.g.

    <project>
      <modelVersion>4.0.0</modelVersion>
      <groupId>com.mycompany.app</groupId>
      <artifactId>my-app</artifactId>
      <version>1</version>
    </project>
    

    注:groupId + artifactId + version 需要时唯一的。在仓库中的名字为 com.mycompany.app:my-app:1

    运行 mvn package 就可以得到一个 JAR文件。

    1.3 Effective POM

    mvn help:effective-pom
    

    会在控制台中输出,相当于 super pom + 当前项目的 pom。

    3. 项目继承 和 项目聚合

    2.1 Project Inheritance 项目继承

    上例提到Super POM是一种特殊的 项目继承。同时,你也可以 自定义 你的项目要继承于哪个。

    Example 1

    在之前的例子中,提到了 com.mycompany.app:my-app:1,假如我们又引入了另外一个项目 com.mycompany.app:my-module:1

    <project>
      <modelVersion>4.0.0</modelVersion>
      <groupId>com.mycompany.app</groupId>
      <artifactId>my-module</artifactId>
      <version>1</version>
    </project>
    

    想要 my-module继承于 my-app,my-module就可以用以下的POM文件

    <project>
      <modelVersion>4.0.0</modelVersion>
     
      <parent>
        <groupId>com.mycompany.app</groupId>
        <artifactId>my-app</artifactId>
        <version>1</version>
      </parent>
     
      <groupId>com.mycompany.app</groupId>
      <artifactId>my-module</artifactId>
      <version>1</version>
    </project>
    

    在这里引入了 ,这个标签就指明了说,我们当前的project的 parent是哪个。这样我们的项目就可以用 parent POM的一些东西了。

    btw: 你项目的groupId 或者 version 要是和 parent的相同的话,你可以删除掉两行,看起来简练一点。

    <project>
      <modelVersion>4.0.0</modelVersion>
     
      <parent>
        <groupId>com.mycompany.app</groupId>
        <artifactId>my-app</artifactId>
        <version>1</version>
      </parent>
     
      <artifactId>my-module</artifactId>
    </project>
    

    2.2 Project Aggregation 项目聚合

    跟 Project Inheritance 类似,但是 Project Inheritance是在 子项目中 指明 父项目 是谁? Project Aggregation 是在父项目中,指代子项目都有谁

    <project>
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.mycompany.app</groupId>
        <artifactId>my-app</artifactId>
        <version>1</version>
        <packaging>pom</packaging>
    
        <module>my-app-service-api</module>
        <module>my-app-infrastructure</module>
        <module>my-app-service</module>
        <module>my-app-start</module>
    </project>
    

    2.3 总结

    要是有很多Maven projects,他们都拥有相似的 配置,就建议把 相似的配置提出来,放到 parent project里面。
    要是有一些project,他们互相依赖,那就建议 用 Module的形式。

    3. Dependency

    3.1 Dependency Scope

    在引用 dependency的时候,scope有两个作用,1 限制dependency的传递;2. 标明这个dependency 在何时有效。

    比如

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.76</version>
    </dependency>
    
    

    compile

    默认的scope。compile dependency在 项目的整个生命周期中都适用,同样,也会传递到依赖的项目中。

    provided

    跟compile相似,但是标明dependency 由 jdk或者容器提供,比如 Servlet AP 和 Java EE APIS,没有传递性。

    runtime

    编译的时候不用,执行的时需要,比如 JDBC。

    test
    只用于测试中,不用于运行时。比如 JUnit Mockito。

    system
    跟 provided相似,但是在系统中要以外部包的形式提供,maven不会在repository中查找它。所有它必须要有一个 systemPath 的标签

    <dependencies>
      <dependency>
       <groupId>javax.sql</groupId>
       <artifactId>jdbc-stdext</artifactId>
       <version>2.0</version>
       <scope>system</scope>
       <systemPath>${java.home}/lib/rt.jar</systemPath>
      </dependency>
    </dependencies>
    

    import

    import只适用于 里面,它是为了解决 maven只支持单继承的问题。比如公司有自己的项目,所以parent必须是公司的项目,但是又想继承于 spring boot,就可以用以下这种写法,标明将 spring-boot-dependencies中的 dependencyManagement的 dependencies,全部引入当前工程的 dependencyManagement

    3.2 Transitive Dependencies 传递依赖

    举个例子,要是 project A 依赖于 Project BProject B 又依赖于 project C,那么就有了依赖传递,这个时候 project A 依赖于 project C

      A
      ├── B
      │   └── C
    

    那这个时候就有个问题,dependency scope是怎么传递的呢? 比如 上例中,引用Project B 的scope是 test,引用Project C的时候是 compile的,那A引用C的时候是什么 scope的呢?

    就可以参考下面的对照关系,列是就是上例中的 project A 引用 project B的 scope,行就是上例中的 project B 引用 Project C的scope ,要是没有值的话,就代表这个dependency会被忽略掉。

    compile provided runtime test
    compile compile - runtime -
    provided provided - provided -
    runtime runtime - runtime -
    test test - test -

    3.2.1 Optional dependencies

    含义:可以主动不把 可以传递的依赖 传递下去。

    例子:如果 B 引用 了C,并且把 Z表明为 Optional。

    那么当 A 引用 B的时候,A就只会引用 B,不会引用 C,即使B和C的scope都是 compile。

    
    <dependencies>
    <!-- declare the dependency to be set as optional -->
        <dependency>
            <groupId>sample.ProjectC</groupId>
            <artifactId>Project-C</artifactId>
            <version>1.0</version>
            <scope>compile</scope>
            <optional>true</optional> <!-- value will be true or false only -->
        </dependency>
    </dependencies>
    

    3.2.2 Excluded denpendencies

    如果 X 引用了Y,Y引用了Z,但是X又不想引用Z,就可以在引用Y的时候,Excluded Z。

    3.2.3 Nearest Definition 最短路径原则

    Example

      A
      ├── B
      │   └── C
      │       └── D 2.0
      └── E
          └── D 1.0
    

    在以上的例子中,对于引用D有两种路径 A -> B -> C -> D 2.0 或者 A -> E -> D 1.0,Maven认为 AED 比 ABCD 短,所以实际引用D的版本号为 1.0。

    Example

    在以上的例子中,要是我们确实想引用 D2.0的话,就可以再加上一个dependency,把整个项目的引用关系变为如下

     A
      ├── B
      │   └── C
      │       └── D 2.0
      ├── E
      │   └── D 1.0
      │
      └── D 2.0 
    

    此时 A -> D 2.0就变成最短的了。

    注:要是路径长度长度相同,就选择第一个出现的版本。

    3.3 dependencyManagement

    这样的好处是:子项目无需再指定dependency的版本号,子项目的dependency的所有版本号 由 parent统一管理。

    用以下这个POM引用举例子

      A
      ├── B
      │   └── C
      │       └── D
      └── E
          └── D
    

    假如有一天,D升级了版本,这个时候需要做的事情是 C 和 E都需要更新升级版本,C升级的话,B也要升级,最终A也要被动升级版本。这样会遇到一个问题,子项目升级版本以后,需要父项目被动的升级版本,项目多的话很可能就传输信息错误了。那么能不能所有的版本管理,由父项目统一管理呢,每次版本更新,只需要更新父项目,变成主动的更新。

    所以对于上面的例子,A项目就可以维护一个 的 section,维护B、C、D、E的版本号。这样 B、C、D、E被引用的时候就不用声明版本号了。

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.my-app</groupId>
                <artifactId>project-b</artifactId>
                <version>${project.b.version}</version>
            </dependency>
            <dependency>
                <groupId>com.my-app</groupId>
                <artifactId>project-c</artifactId>
                <version>${project.c.version}</version>
            </dependency>
            ......
        </dependencies>
    </dependencyManagement>
    

    假如 C引用D的时候,没有版本号,此时

    MAVEN的逻辑是:

    • 要是指定了 Version,那就取指定 Version的dependency。
    • 要是没有指定 Version,就去parent里面的 tag下找,有无这个dependency的声明,有的话取这个版本的 dependency,没有的话报错。

    参考链接

    1. Maven - Ref links
    2. maven/pom-4.0.0.xml · apache/maven
    3. Maven – Introduction to the POM
    4. Maven – POM Reference
    5. Maven: The Complete Reference - The Nexus

  • 相关阅读:
    把一个List拆分为几个大小一样的List
    错误统一捕捉处理新方式
    1014 C语言文法定义与C程序的推导过程
    0917 词法分析
    0909 对编译原理的理解
    mysql索引
    sql优化的基本原则
    分布式文件系统memcache和ehcache
    Java多线程与并发控制
    HTTP报文
  • 原文地址:https://www.cnblogs.com/hchengmx/p/15085639.html
Copyright © 2020-2023  润新知