maven pom.xml详解

什么是pom.xml

POM是项目对象模型(Project Object Model)的简称,它是Maven项目中的文件,使用XML表示,名称叫做pom.xml。作用类似ant的build.xml文件,功能更强大。该文件用于管理:源代码、配置文件、开发者的信息和角色、问题追踪系统、组织信息、项目授权、项目的url、项目的依赖关系等等。事实上,在Maven世界中,project可以什么都没有,甚至没有代码,但是必须包含pom.xml文件。

概览

下面是pom.xml文件中包含的元素。注意,modelVersion包含4.0.0。这是目前唯一支持的POM版本,并且始终是必需的。

<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>

pom基础属性

对于一个pom.xml来说有几个元素是必须定义的,一个是project根元素,然后就是它里面的modelVersion、groupId、artifactId和version。当然这其中的元素也是可以从它的父项目中继承的。

<?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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <!-- 
        含义:组织标识,定义了项目属于哪个组,风向标,坐标,或者说若把本项目打包
        用途:此名称则是本地仓库中的路径,列如:org.codehaus.mojo,在M2_REPO目录下,将是: org/codehaus/mojo目录
        命名规范:项目名称,模块,子模块
    -->
    <groupId>org.codehaus.mojo</groupId>

    <!-- 
        含义:项目名称也可以说你所模块名称,定义当面Maven项目在组中唯一的ID
        用途:例如:my-project,在M2_REPO目录下,将是:org/codehaus/mojo/my-project目录
        命名规范:唯一就好
    -->
    <artifactId>my-project</artifactId>

    <!-- 
        含义:项目当前的版本号
        用途:例如:0.0.1-SNAPSHOT,在M2_REPO目录下,将是:org/codehaus/mojo/my-project/0.0.1-SNAPSHOT目录
    -->
    <version>0.0.1-SNAPSHOT</version>

    <!-- 打包的格式,默认为 jar。可以为:pom , jar , maven-plugin , ejb , war , ear , rar , par -->
    <packaging>war</packaging>


    <!-- 元素声明了一个对用户更为友好的项目名称 -->
    <name>maven</name>
</project>

pom.xml 继承

被继承项目与继承项目是父子目录关系

现在假设我们有一个项目projectA,它的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
                      https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>projectA</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>pom</packaging>
</project>

然后我们有另一个项目projectB,而且projectB是跟projectA的pom.xml文件处于同一个目录下,这时候如果projectB需要继承自projectA的话我们可以这样定义projectB的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/maven-v4_0_0.xsd">  
  <parent>  
    <groupId>org.codehaus.mojo</groupId>  
    <artifactId>projectA</artifactId>  
    <version>1.0-SNAPSHOT</version>  
  </parent>  
  <modelVersion>4.0.0</modelVersion>  
  <groupId>org.codehaus.mojo</groupId>  
  <artifactId>projectB</artifactId>  
  <packaging>pom</packaging>  
  <version>1.0-SNAPSHOT</version>  
</project>

被继承项目与继承项目的目录结构不是父子关系

当被继承项目与继承项目的目录结构不是父子关系的时候,我们再利用上面的配置是不能实现Maven项目的继承关系的,这个时候我们就需要在子项目的pom.xml文件定义中的parent元素下再加上一个relativePath元素的定义,用以描述父项目的pom.xml文件相对于子项目的pom.xml文件的位置。

假设我们现在还是有上面两个项目,projectA和projectB,projectB还是继承自projectA,但是现在projectB不在projectA的子目录中,而是与projectA处于同一目录中。这个时候projectA和projectB的目录结构如下:

       ------projectA

              ------pom.xml

       ------projectB

              ------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/maven-v4_0_0.xsd">  
  <parent>  
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>projectA</artifactId>
    <version>1.0-SNAPSHOT</version>
    <relativePath>../projectA/pom.xml</relativePath>
  </parent>  
  <modelVersion>4.0.0</modelVersion>  
  <groupId>org.codehaus.mojo</groupId>  
  <artifactId>projectB</artifactId>  
  <packaging>pom</packaging>  
  <version>1.0-SNAPSHOT</version>  
</project>

聚合 modules

使用 modules 聚合时,要重新创建一个聚合到项目模块,然后在这个项目模块里添加要聚合的项目。不能直接修改父项目的pom.xml里面的modules,如果修改了就会影响父子项目。

比如说如果projectA聚合到projectB,那么我们就可以说projectA是projectB的子模块, projectB是被聚合项目,也可以类似于继承那样称为父项目。对于聚合而言,这个主体应该是被聚合的项目。所以,我们需要在被聚合的项目中定义它的子模块,而不是像继承那样在子项目中定义父项目。具体做法是:

  • 修改被聚合项目的pom.xml中的packaging元素的值为pom(该项目就不能docker发布,因为要发布package要jar)
  • 在被聚合项目的pom.xml中的modules元素下指定它的子模块项目

对于聚合而言,当我们在被聚合的项目上使用Maven命令时,实际上这些命令都会在它的子模块项目上使用。这就是Maven中聚合的一个非常重要的作用。假设这样一种情况,你同时需要打包或者编译projectA、projectB、projectC和projectD,按照正常的逻辑我们一个一个项目去使用mvn compile或mvn package进行编译和打包,对于使用Maven而言,你还是这样使用的话是非常麻烦的。因为Maven给我们提供了聚合的功能。我们只需要再定义一个超级项目,然后在超级项目的pom.xml中定义这个几个项目都是聚合到这个超级项目的。之后我们只需要对这个超级项目进行mvn compile,它就会把那些子模块项目都进行编译。

<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>org.codehaus.mojo</groupId>
  <artifactId>projectA</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>pom</packaging>

  <modules>
        <!--
            projectA 和 projectB 是父子关系
            -->
       <module>projectB</module>

        <!--
            projectA 和 projectC 是不是父子关系
            相对路径
            -->
       <module>../projectC</module>
  </modules>  
</project>  

依赖 Dependency

项目之间的依赖是通过pom.xml文件里面的dependencies元素下面的dependency元素进行的。一个dependency元素定义一个依赖关系。在dependency元素中我们主要通过依赖项目的groupId、artifactId和version来定义所依赖的项目。

<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>org.codehaus.mojo</groupId>  
  <artifactId>projectB</artifactId>  
  <version>1.0-SNAPSHOT</version>  
  <packaging>jar</packaging>  
   
  <dependencies>  
    <dependency>  
      <groupId>junit</groupId>  
      <artifactId>junit</artifactId>  
      <version>3.8.1</version>  
      <scope>test</scope>  
              <optional>true</optional>  
    </dependency>  
  </dependencies>  
</project>  

在dependency元素中除了可以指定依赖项目的groupId、artifactId和version之外,还可以指定以下元素:

  • type:对应于依赖项目的packaging类型,默认是jar
  • scope:表示依赖项目的一个作用范围。scope的主要取值范围如下

compile:这是它的默认值,这种类型很容易让人产生误解,以为只有在编译的时候才是需要的,其实这种类型表示所有的情况都是有用的,包括编译和运行时。而且这种类型的依赖性是可以传递的。

provided:这个跟compile很类似,但是它表示你期望这个依赖项目在运行时由JDK或者容器来提供。这种类型表示该依赖只有在测试和编译的情况下才有效,在运行时将由JDK或者容器提供。这种类型的依赖性是不可传递的。

runtime:这种类型表示该依赖在编译的时候不是必须的,只有在运行的时候才是必须的。

test:这表示这种依赖只有测试的时候才需要,正常情况下是不需要的。

system:这种类型跟provided类似,唯一不同的就是这种类型的依赖我们要自己提供jar包,这需要与另一个元素systemPath来结合使用。systemPath将指向我们系统上的jar包的路径,而且必须是给定的绝对路径。

  • systemPath:上面已经说过了这个元素是在scope的值为system的时候用于指定依赖的jar包在系统上的位置的,而且是绝对路径。该元素必须在依赖的 jar包的scope为system时才能使用,否则Maven将报错。
  • optional:当该项目本身作为其他项目的一个依赖时标记该依赖为可选项。假设现在projectA有一个依赖性projectB,我们把projectB这个依赖项设为optional,这表示projectB在projectA的运行时不一定会用到。这个时候如果我们有另一个项目projectC,它依赖于projectA,那么这个时候因为projectB对于projectA是可选的,所以Maven在建立projectC的时候就不会安装projectB,这个时候如果projectC确实需要使用到projectB,那么它就可以定义自己对projectB的依赖。当一个依赖是可选的时候,我们把optional元素的值设为true,否则就不设置optional元素。
  • exclusions:考虑这样一种情况,我们的projectA依赖于projectB,然后projectB又依赖于projectC,但是在projectA里面我们不需要projectB依赖的projectC,那么这个时候我们就可以在依赖projectB的时候使用exclusions元素下面的exclusion排除projectC。这个时候我们可以这样定义projectA对projectB的依赖:
<dependencies>  
     <dependency>  
            <groupId>org.codehaus.mojo</groupId>  
            <artifactId>projectB</artifactId>  
            <version>1.0-SNAPSHOT</version>  
            <exclusions>  
                   <exclusion>  
                          <groupId>org.codehaus.mojo</groupId>  
                          <artifactId>projectC</artifactId>  
                   </exclusion>  
            </exclusions>  
     </dependency>  
</dependencies>  

聚合与继承的关系

  1. 聚合主要是为了方便快速构建项目,继承主要是为了消除重复配置
  2. 对于聚合模块而言,它知道有哪些被聚合的模块,但那些被聚合的模块不知道这个聚合模块的存在;对于继承的父pom而言,它不知道有哪些子模块继承它,但那些子模块都必须知道自己的父POM是什么
  3. 聚合POM与继承中的父POM的packaging都必须是pom;同时,聚合模块与继承中的父模块除了POM外,都没有实际的内容

 

转自:https://www.iteye.com/blog/elim-2055745

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值