zoukankan      html  css  js  c++  java
  • Maven聚合与继承

    本文将在以下三部分进行编写:

    1. POM文件解析
    2. 构建顺序
    3. 可选择性部署

     Maven聚合即可以将多个子模块聚合在一起进行构建,继承即所有子模块均可以继承父模块的属性、依赖和插件等,可消除重复配置。

    Maven基础性的知识不在此赘述,本文中涉及的Maven关键标签包括:

    • packaging:打包方式,常见的有jar(默认)、war和pom等;
    • module:子模块声明
    • properties:属性,可定义依赖报的版本号、定义某些插件的配置等;
    • dependencyManagement:依赖管理,具有依赖管理的POM,即不会给父模块引入依赖,也不会给子模块引入依赖。只有子模块声明依赖的使用(只需groupId和artifactId即可指明所用依赖),才会引入依赖包。使用import范围依赖导入依赖管理配置暂不讨论;
    • pluginManagement:插件管理,与依赖管理类似,该元素的配置不会实际插件调用的行为,只有当POM中正在配置对应的plugin元素才起作用;
    • repositories:用于声明远程仓库,可以是私有仓库(可由nexus搭建)。所有POM文件都会继承Maven顶级POM,其中包含Maven中央仓库。
    • distributionManagement:部署管理,可部署到远程Maven仓库,支持snapshotRepository和repository分别对应快照和稳定版本。

    举一个比较常见的例子,假设某项目project包含三个模块,分别是:project_a、project_b、project_c,其文件结构如下,三个子模块与pom.xml在同一级,与父模块是父子目录结构:

    /project
        /project_a
        /project_b
        /project_c
        pom.xml

    1. POM文件解析

    父模块project

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <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">
     3   <modelVersion>4.0.0</modelVersion>
     4   <groupId>com.test</groupId>
     5   <artifactId>project</artifactId>
     6   <version>0.0.1-SNAPSHOT</version>
     7   <packaging>pom</packaging>
     8   <modules>
     9     <module>project_a</module>
    10     <module>project_b</module>
    11     <module>project_c</module>
    12   </modules>
    13   
    14   <properties>
    15       <spring.version>4.3.1.RELEASE</spring.version>
    16   </properties>
    17   
    18   <dependencyManagement>
    19       <dependencies>
    20           <dependency>
    21             <groupId>org.springframework</groupId>
    22             <artifactId>spring-aop</artifactId>
    23             <version>${spring.version}</version>
    24         </dependency>
    25         ......
    26         <dependency>
    27             <groupId>org.springframework</groupId>
    28             <artifactId>spring-core</artifactId>
    29             <version>${spring.version}</version>
    30         </dependency>
    31       </dependencies>
    32   </dependencyManagement>
    33   
    34   <build>
    35       <pluginManagement>
    36           <plugins>
    37               <plugin>
    38                 <groupId>org.apache.maven.plugins</groupId>
    39                 <artifactId>maven-compiler-plugin</artifactId>
    40                 <version>3.1</version>
    41                 <configuration>
    42                     <source>1.7</source>
    43                     <target>1.7</target>
    44                 </configuration>
    45             </plugin>
    46               ......
    47               <plugin>
    48                 <groupId>org.apache.maven.plugins</groupId>
    49                 <artifactId>maven-surefire-plugin</artifactId>
    50                 <version>2.12.4</version>
    51                 <configuration>
    52                     <skipTests>true</skipTests>
    53                 </configuration>
    54             </plugin>
    55           </plugins>
    56       </pluginManagement>
    57   </build>
    58   
    59   <repositories>
    60         <repository>
    61             <id>nexus</id>
    62             <name>maven repository</name>
    63             <url>http://serverip:port/nexus/content/groups/public/</url>
    64             <snapshots>
    65                 <enabled>true</enabled>
    66             </snapshots>
    67             <releases>
    68                 <enabled>true</enabled>
    69             </releases>
    70         </repository>
    71     </repositories>
    72     
    73     <!-- 发布 构件 到 私服 -->
    74     <distributionManagement>
    75         <repository>
    76             <id>nexus</id>
    77             <name>releases</name>
    78             <url>http://serverip:port/nexus/content/repositories/releases/</url>
    79         </repository>
    80 
    81         <snapshotRepository>
    82             <id>nexus</id>
    83             <name>snapshots</name>
    84             <url>http://serverip:port/nexus/content/repositories/snapshots/</url>
    85         </snapshotRepository>
    86     </distributionManagement>
    87 </project>
    •  4-6行:声明该构件在Maven仓库中的唯一坐标;
    • 7行: 打包方式为pom,起聚合作用的父模块必须声明为pom方式,否则构建失败;
    • 8-12行:聚合三个子模块project_a、project_b、project_c,每个module的值代表当前POM的相对目录,如果三个子模块与父模块是平行目录结构,则值应该为 ../project_a
    • 14-16行:定义POM属性,其可由子模块继承,在此声明为spring版本号;
    • 18-32行:配置依赖管理,对工程不会引入依赖,只有真正声明对应依赖才会引入;
    • 34-57行:配置插件管理,同依赖管理;
    • 59-71行:配置远程Maven仓库,需要在setting.xml中配置远程Maven仓库的用户名与密码等信息,如下:
    <servers>
        <server>  
        <id>nexus</id>  
        <username>admin</username>  
        <password>admin123</password>  
        </server>  
    </servers>
    •  74-86行:发布构件到私服配置,其他开发者可以使用该构件

    子模块(project_a)

     1 <?xml version="1.0"?>
     2 <project
     3     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
     4     xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
     5     <modelVersion>4.0.0</modelVersion>
     6     <parent>
     7         <groupId>com.test</groupId>
     8         <artifactId>project</artifactId>
     9         <version>0.0.1-SNAPSHOT</version>
    10     </parent>
    11     <artifactId>project_a</artifactId>
    12     <name>project_a</name>
    13     
    14     <dependencies>
    15         <dependency>
    16             <groupId>org.springframework</groupId>
    17             <artifactId>spring-aop</artifactId>
    18         </dependency>
    19         ......
    20         <dependency>
    21             <groupId>org.springframework</groupId>
    22             <artifactId>spring-core</artifactId>
    23         </dependency>
    24     </dependencies>
    25     
    26     <build>
    27         <plugins>
    28             <plugin>
    29                 <groupId>org.apache.maven.plugins</groupId>
    30                 <artifactId>maven-compiler-plugin</artifactId>
    31             </plugin>
    32               ......
    33               <plugin>
    34                 <groupId>org.apache.maven.plugins</groupId>
    35                 <artifactId>maven-surefire-plugin</artifactId>
    36             </plugin>
    37         </plugins>
    38     </build>
    39 </project>
    •  6-10行:由parent元素声明该模块的父模块为project,其中省略了<relativePath>,该元素标识父模块POM的相对位置(由父模块与子模块的目录结构决定),默认值为 ../pom.xml,在本例子中为默认值;
    • 11-12行:由于继承了父模块中的所有配置,此处只需要声明artifactId即可,groupId与version继承自父模块。name元素用于描述,在构建日志找那个将显示该名;
    • 14-24行:真正声明所需依赖,会为该模块引入对应依赖,只需groupId和artifactId;
    • 26-38行:真正声明所需插件,也只需groupId和artifactId;

    2. 构建顺序

    在对工程只需 mvn clean install等命令的时候,Maven会首先解析聚合模块的POM、分析要构建的模块、并计算出一个反应堆构建顺序(Reactor Build Order),然后根据这个顺序依次构建模块。其中反应堆是所有模块组成的一个构建结构,包含各模块之间的继承与依赖关系,计算合理的模块构建顺序。(模块构建具体经历过哪些过程,可学习Maven中的生命周期)。

    假设三个模块之间存在一定的依赖关系,如图:

    本工程的构建顺序如下,聚合模块project、project_a、project_c、project_b:

    [INFO] Scanning for projects...
    [INFO] ------------------------------------------------------------------------
    [INFO] Reactor Build Order:
    [INFO] 
    [INFO] project
    [INFO] project_a
    [INFO] project_c
    [INFO] project_b
    [INFO]                                                                         
    [INFO] ------------------------------------------------------------------------

     还可以通过命令行对反应堆进行裁剪,包括:

    • -am, --also-make 同时构建所列模块的依赖模块
    • -amd, --also-make-dependents 同时构建依赖于所列模块的模块
    • -pl, --projects <arg> 构建指定的模块,模块间用逗号分隔
    • -rf,-resume-form <arg> 从指定模块开始构建

    举例:mvn clean install -pl project_a,project_b

    [INFO] Scanning for projects...
    [INFO] ------------------------------------------------------------------------
    [INFO] Reactor Build Order:
    [INFO] 
    [INFO] project_a
    [INFO] project_b
    [INFO]                                                                         
    [INFO] ------------------------------------------------------------------------

     mvn clean install -pl project_a -am

    [INFO] Scanning for projects...
    [INFO] ------------------------------------------------------------------------
    [INFO] Reactor Build Order:
    [INFO] 
    [INFO] project
    [INFO] project_a
    [INFO]                                                                         
    [INFO] ------------------------------------------------------------------------

     mvn clean install -pl project_a -amd

    [INFO] Scanning for projects...
    [INFO] ------------------------------------------------------------------------
    [INFO] Reactor Build Order:
    [INFO] 
    [INFO] project_a
    [INFO] project_c
    [INFO] project_b
    [INFO]                                                                         
    [INFO] ------------------------------------------------------------------------

     mvn clean install -pl project_a -amd -rf project_c

    [INFO] Scanning for projects...
    [INFO] ------------------------------------------------------------------------
    [INFO] Reactor Build Order:
    [INFO] 
    [INFO] project_c
    [INFO] project_b
    [INFO]                                                                         
    [INFO] ------------------------------------------------------------------------

    3. 可选择性部署

    在父模块中声明了distributionManagement,在执行 mvn deploy的时候,会将所有的模块部署到远程服务器上。如何做到有选择性的的部署呢?比如不想将project_a部署到Maven仓库,有两种方式:

    (1)在properties元素中声明 maven.deploy.skip

      在project_a模块的POM文件中添加如下配置:

    <properties>
          <maven.deploy.skip>true</maven.deploy.skip>
    </properties>

     (2)声明子模块插件,覆盖父模块插件

    在project_a模块的POM文件中,添加属于自己的部署插件:

    <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-deploy-plugin</artifactId>
           <version>2.4</version>
           <configuration>
                <skip>true</skip>
           </configuration>
     </plugin>

    注意: 在部署的时候,不想将父POM工程部署到远程仓库,此时怎么办?需要注意的是如果在父POM中声明跳过部署,则所有子POM工程继承该属性而跳过部署。解决方案:父POM声明跳过部署,子POM覆盖该属性,声明为false。

    总结

    • POM的聚合与继承,前者方便快捷构建项目,后者可以消除重复配置;
    • 除了本文举的例子,可以在聚合模块任意文件夹什么父模块,只需要改变module和relativePath的相对路径即可;
    • 根据反应堆对各模块间依赖关系的计算,形成合理的构建顺序,并可以对构建顺序进行裁剪;
    • 可以通过插件属性配置,实现模块可选择的部署;

    参考:

  • 相关阅读:
    5.颜色空间转换
    Linux下的解压命令
    4.图像模糊/图像平滑
    insightface作者提供数据训练解读
    MXNetError: [05:53:50] src/operator/nn/./cudnn/cudnn_convolution-inl.h:287
    python中import cv2遇到的错误及安装方法
    docker 安装 mxnet
    95. Unique Binary Search Trees II
    236. Lowest Common Ancestor of a Binary Tree
    124. Binary Tree Maximum Path Sum
  • 原文地址:https://www.cnblogs.com/shuimuzhushui/p/7822719.html
Copyright © 2011-2022 走看看