zoukankan      html  css  js  c++  java
  • Maven POM元素继承

            为了减少重复代码的编写,我们需要创建POM的父子结构,然后在POM中申明一些配置供子POM继承,以实现“一处申明,多处使用的”目的。以之前的模块中的结构为基础,在account-aggregator下创建一个account-parent的子目录,然后在该子目录下创建除account-aggregator模块之外的模块的父模块。为此在该子目录下创建一个pom.xml文件如下:

    <?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>  
            <groupId>com.juvenxu.mvnbook.account</groupId>  
            <artifactId>account-parent</artifactId>  
            <version>1.0.0-SNAPSHOT</version>  
            <packaging>pom</packaging>  
            <name>Account Parent</name>     
    </project> 

            需要注意的是它的packaging的值必须为pom,这一点与模块聚合一样,作为负模块的POM,其打包类型也必须为pom。由于父模块只是为了消除配置的重复,因此也就不需要src/main/java等目录了。

            有了父模块就让其他子模块来继承它,修改account-email的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/maven-v4_0_0.xsd">  
    <modelVersion>4.0.0</modelVersion> 
            <parent>
                <groupId>com.juvenxu.mvnbook.account</groupId>  
                <artifactId>account-parent</artifactId>  
                <version>1.0.0-SNAPSHOT</version>  
                <relativePath>../account-parent/pom.xml</relativePath>  
            </parent> 
            <artifactId>account-email</artifactId> 
            <name>Account Email</name> 
    
            <dependencies>
                    ......
            </dependencies>
    
            <build>
                    <plugins>
                        ......
                    </plugins>
            </build>
    
    </project>

            parent下的子元素groupId、artifactId和version指定了父模块的坐标,这三个元素是必须的。元素relativePath表示父模块POM的相对路径。当项目构建时,Maven会首先根据relativePath检查父POM,如果找不到,再从本地仓库查找。relativePath的默认值是../pom.xml,也就是说,Maven默认父POM在上一层目录下。

            这个更新过的POM文件并没为account-email设置artifactId和version,实际上这个子模块隐式的从父模块继承了这两个元素。如果子模块中遇到与父模块中不一样的artifactId、version这个时候应该在子模块显示声明。

            最后还要把父模块加入到聚合模块account-aggregator中如下:

    <?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>  
            <groupId>com.juvenxu.mvnbook.account</groupId>  
            <artifactId>account-aggregator</artifactId>  
            <version>1.0.0-SNAPSHOT</version>  
            <packaging>pom</packaging>  
            <name>Account Aggregator</name>  
            <modules>
                 <module>account-parent</module>    
                 <module>account-email</module>  
                 <module>account-persist</module>  
            <modules>     
    </project>    

    此时的目录结构是account-parent、account-email、account-persist在同一级目录,account-aggregator为三个目录的父目录。

    可继承的POM元素如下:

    • groupId:项目组ID,项目坐标的核心元素
    • version:项目版本,项目坐标的核心因素
    • description:项目的描述信息
    • organization:项目的组织信息
    • inceptionYear:项目的创始年份
    • url:项目的URL地址
    • developers:项目的开发者信息
    • contributors:项目的贡献者信息
    • distributionManagement:项目的部署配置
    • issueManagement:项目的缺陷跟踪系统信息
    • ciManagement:项目的持续集成系统信息
    • scm:项目的版本控制系统西溪
    • malilingLists:项目的邮件列表信息
    • properties:自定义的Maven属性
    • dependencies:项目的依赖配置
    • dependencyManagement:项目的依赖管理配置
    • repositories:项目的仓库配置
    • build:包括项目的源码目录配置、输出目录配置、插件配置、插件管理配置等
    • reporting:包括项目的报告输出目录配置、报告插件配置等

      依赖管理

      因为dependencies元素也是可继承的,因此我们可以把公共的jar放到父模块account-parent中,比如org.springframework:spring-core:2.5.6在account-email,account-persist模块中都会用到,因此可以将这个依赖配置放到父模块中,两个子模块就能移除这些依赖从而简化配置。

      上述做法是可行的,但是存在问题。因为所有的子模块都会继承以上父模块的依赖项,不管子模块是否真的需要此依赖项。这样相当于子模块失去了这些依赖项继承的选择权。假设后面加了模块acount-util与springframework没有半毛钱关系,让他依赖spring的依赖项显然是不合理的。

      为此Maven提供了dependencyManagement元素既能让子模块继承到父模块的依赖配置,又能保证子模块依赖的使用灵活性。在dependencyManagement元素下的依赖声明不会引入到实际的依赖,不过它能约束dependencies下的依赖使用。

    <?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>  
            <groupId>com.juvenxu.mvnbook.account</groupId>  
            <artifactId>account-parent</artifactId>  
            <version>1.0.0-SNAPSHOT</version>  
            <packaging>pom</packaging>  
            <name>Account Parent</name> 
            <properties>
                    <springframework.version>2.5.6</springframework.version>
            </properties>
    
            <dependencyManagement>
                    <dependencies>
                           <dependency>
                                <groupId>org.springframework </groupId>
                                <artifactId>spring-core</artifactId>
                                <version>${springframework.version}</version>
                           </dependency>
    
                           ......
    
                    </dependencies>
            </dependencyManagement>
    </project>     

      这里使用了dependencyManagement声明的依赖既不会给account-parent引入依赖项,也不会给他的子模块引入依赖,不过这段配置会被继承。现在修改account-email的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/maven-v4_0_0.xsd">  
    <modelVersion>4.0.0</modelVersion> 
            <parent>
                <groupId>com.juvenxu.mvnbook.account</groupId>  
                <artifactId>account-parent</artifactId>  
                <version>1.0.0-SNAPSHOT</version>  
                <relativePath>../account-parent/pom.xml</relativePath>  
            </parent> 
            <artifactId>account-email</artifactId> 
            <name>Account Email</name> 
    
            <dependencies>
                    <dependency>
                        <groupId>org.springframework</groupId>
                        <artifactId>spring-core</artifactId>
                    </dependency>
                    
                    ......
                    
            </dependencies>
    
            <build>
                    <plugins>
                        ......
                    </plugins>
            </build>
    
    </project>

      上面的配置较原来简单了一些,只配置了groupId和artifactId,省去了version,如果父模块配置了依赖的scope也是可以省略的。这些信息可以省略是因为account-email继承了account-parent中的dependencyManagement配置,完整的依赖声明已经包含在父POM中了,子模块只需简单的配置groupId和artifactId。

      使用这种以来管理机制虽然不能减少太多的配置项,但是经过别人实践后强烈推荐的方法。如果子模块不声明依赖的使用,即使该依赖已经在父POM文件dependencyManagement中声明了,也不会产生任何实际的效果。

    插架管理

      Maven提供了dependencyManagement元素帮助管理依赖,类似的,Maven也提供了pluginManagement元素帮助管理插件。当子模块POM中配置了plugin,并且groupId和artifactId与pluginManagement中的配置的插件匹配时,pluginManagement的配置才会真正影响实际插件的行为。

      父POM文件:

      <build>
      <pluginManagement>
      <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-source-plugin</artifactId>
        <version>2.1.2</version>
        <executions>
          <execution>
            <id>attach-sources</id>
            <phase>verify</phase>
            <goals>
              <goal>jar-no-fork</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      </plugins>
      </pluginManagement>
      </build>

      在子模块继承pluginManagement后的插件配置

      <build>
          <plugins>
              <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
              </plugin>
            </plugins>
      </build>

    聚合与继承的关系

    区别 :

    1.对于聚合模块来说,它知道有哪些被聚合的模块,但那些被聚合的模块不知道这个聚合模块的存在。

    2.对于继承关系的父 POM来说,它不知道有哪些子模块继承与它,但那些子模块都必须知道自己的父 POM是什么。

     

    共同点 :

    1.聚合 POM与继承关系中的父POM的 packaging都是pom

    2.聚合模块与继承关系中的父模块除了 POM之外都没有实际的内容。

    Maven聚合关系与继承关系的比较
     
    现有的实际项目往往是一个POM既是聚合POM又是父POM,这么做主要是为了方便。
     
    反应堆:
      在一个多模块的Maven项目中,反应堆是指所有模块组成的一个构建结构。反应堆包含了各个模块之间的继承与依赖关系,从而能够自动计算出合理的模块构建顺序。
    <modules>  
      <module>account-email</module>  
      <module>account-persist</module>  
      <module>account-parent</module>  
    </modules> 

      实际的构建顺序为: ~parent, ~email, ~persist。

      可见构建的顺序并不是声明的顺序。

      该例中account-email和account-persist都依赖于account-parent,那么account-parent就必须在另外两个模块之前构建。实际的构建顺序是这样的:Maven按声明顺序读取POM,如果POM没有依赖模块,那么久构建该模块,否则就先构建其依赖的模块。,如果依赖的模块还依赖于其他模块,则进一步构建依赖的依赖。

      模块之间的关系将反应堆构成一个有向非循环图,各个模块是该图的节点,依赖关系构成又向边,这个图不允许出现循环,因此当出现A依赖于B,B又依赖于A的情况时Maven就会报错。

    裁剪反应堆:

    mvn -h可以看到这样一些选项:

    Options:  
     -am,--also-make                        If project list is specified, also  
                                            build projects required by the  
                                            list  
     -amd,--also-make-dependents            If project list is specified, also  
     -pl,--projects <arg>                   Build specified reactor projects  
                                            instead of all projects. A project  
                                            can be specified by  
                                            [groupId]:artifactId or by its  
                                            relative path.  
     -rf,--resume-from <arg>                Resume reactor from specified  
                                            project  

      有的时候因为工程巨大,模块很多,只想构建指定的模块,这时候就会用到反应堆裁剪。

    -pl 构建指定模块
    mvn clean install -pl accouont-email,account-persist后会得到如下几个模块:~email和~persist。

    -am 选项可以同时构建所列模块的依赖模块。
    当执行mvn clean install -pl account-email -am 后会得到如下几个模块:~parent和~email。

    -amd 选项可以同时构建依赖于所列模块的模块。
    mvn clean install -pl account-parent -amd 后会得到如下模块:~parent、~email和~persist。

    -rf 选项可以在完整的反应堆构建顺序基础上,指定从哪个模块开始构建。
    mvn clean install -rf account-email ,由于~email位于第三,它之后有~persist,因此会得到如下输出模块:~email和~persist。

    在-pl -am或者-pl -amd的基础上,还能应用-rf参数,以对裁剪后的反应堆再次裁剪。
    mvn clean install -pl account-parent -amd -rf account-email
    其中,-pl 和 -amd参数会得到:~parent, ~email和~persist模块,在此基础上 -rf参数制定从~email开始构建,于是会得到:~email和~persist。

  • 相关阅读:
    sizeof
    {面试题10: 二进制中1的个数}
    {面试题9: 斐波那契数列}
    gcc常用选项
    mount.nfs: access denied by server while mounting localhost:/home/xuwq/minilinux/system
    ubuntu bash提示找不到文件或目录
    linux 编译内核[scripts/kconfig/dochecklxdialog] 错误
    最简单的抓包程序
    linux命令行解析函数介绍
    逻辑地址到线性地址的转换
  • 原文地址:https://www.cnblogs.com/maxiaofang/p/5944362.html
Copyright © 2011-2022 走看看