06 Maven 聚合和继承
Maven 聚合和继承
1. 聚合
2. 继承
<parent>
<groupId>org.apache.karaf.demos</groupId>
<artifactId>demos</artifactId>
<version>4.1.5</version>
<relativePath>../pom.xml</relativePath>
</parent>
正确设置 relativepath 非常重要。考虑这样一个情况,开发团队的新成员从源码库签出一个包含父子模块关系的 Maven 项目。由于只关心其中的某一个子模块,它就直接到该模块的目录下执行构建,这个时候,父模块是没有被安装到本地仓库的,因此如果子模块没有设置正确的的 relativepath, Maven 将无法找到父 POM,这将直接导致构建失败。如果 Maven 能够根据 relativepath 找到父 POM,它就不需要再去检査本地仓库。
2.1 可继承的 POM 元素
groupId 和 version 是可以被继承的,那么还有哪些 POM 元素可以被继承呢?以下是一个完整的列表,并附带了简单的说明:
groupId
项目组ID,项目坐标的核心元素version
项目版本,项目坐标的核心元素description
项目的描述信息organization
项目的组织信息。inceptionYear
项目的创始年份。url
项目的URL地址。developers
项目的开发者信息。contributors
项目的贡献者信息。distributionManagement
项目的部署配置。issueManagement
项目的缺陷跟踪系统信息ciManagement
项目的持续集成系统信息。scm
项目的版本控制系统信息。mailinglists
项目的邮件列表信息properties
自定义的 Maven 属性。dependencies
项目的依赖配置。dependencyManagement
项目的依赖管理配置。repositories
项目的仓库配置。build
包括项目的源码目录配置、输出目录配置、插件配置、插件管理配置等。reporting
包括项目的报告输出目录配置、报告插件配置等。
2.2 依赖管理
<dependencyManagement>
</dependencyManagement>
2.3 插件管理
<build>
<pluginManagement>
</pluginManagement>
</build>
2.4 聚合与继承的关系
对于聚合模块来说,它知道有哪些被聚合的模块,但那些被聚合的模块不知道这个聚合模块的存在。
对于继承关系的父 POM 来说,它不知道有哪些子模块继承于它,但那些子模块都必须知道自己的父 POM 是什么。
如果非要说这两个特性的共同点,那么可以看到,聚合 POM 与继承关系中的父 POM 的 packaging 都必须是 pmn,同时,聚合模块与继承关系中的父模块除了 POM 之外都没有实际的内容,如图1 所示
图6.1 聚合关系与继承关系的比较
3. 约定优于配置
Maven 提倡“约定优于配置”(Convention Over Configuration),这是 Maven 最核心的设计理念之一。
那么为什么要使用约定而不是自己更灵活的配置呢?原因之一是,使用约定可以大量减少配置。Maven 只需要一个最简单的 POM 就可以搞定。
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.karaf.demos</groupId>
<artifactId>org.apache.karaf.demos.branding.shell</artifactId>
<version>4.1.5</version>
</project>
这段配置简单得令人惊奇,但为了获得这样简洁的配置,用户是需要付出一定的代价的,那就是遵循 Maven 的的约定。Maven 会假设用户的项目是这样的:
- 源码目录为 src/main/java/
- 编译输出日录为 targel/classes
- 打包方式为 jar 包
- 输出目录为 target/
遵循约定虽然损失了一定的灵活性,用户不能随意安排目录结构,但是却能减少配置。更重要的是,遵循约定能够帮助用户遵守构建标准。
也许这时候有读者会问,如果我不想遵守约定该怎么办?这时,请首先问自己三遍,你真的需要这么做吗?如果仅仅是因为喜好,就不要要个性,个性往往意味着辆牲通用性,意味着增加无谓的复杂度:例如, Maven 允许你自定义源码目录:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.karaf.demos</groupId>
<artifactId>org.apache.karaf.demos.branding.shell</artifactId>
<version>4.1.5</version>
<build>
<sourceDirectory>src/java</sourceDirectory>
</build>
</project>
该例中源码目录就成了 src/java 而不是默认的 src/main/java。但这往往会造成交流问题,习惯 Maven 的人会奇怪,源代码去哪里了?当这种自定义大量存在的时候,交流成本就会大大提高。只有在一些特殊的情况下,这种自定义配置的方式才应该被正确使用以解决实际问题。例如你在处理遗留代码,并且没有办法更改原来的目录结构,这个时候就只能让 Maven 妥协。
本书曾多次提到超级 POM,任何一个 Maven 项目都隐式地继承自该 POM,这有点类似于任何一个 Java 类都隐式地继承于 Object 类。서此,大量超级 POM 的配置都会被所有 Maven 项目继承,这些配置也就成为了 Maven 所提倡的约定。对于 Maven3 超级 POM 在在文件 $MAVEN_HOME/lib/maven-model-builder-3.5.0.jar 中的 org/apache/maven/model/pom-4.0.0.xml 路径下。
<repositories>
<repository>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
<releases>
<updatePolicy>never</updatePolicy>
</releases>
</pluginRepository>
</pluginRepositories>
首先超级 POM 定义了仓库及插件仓库,两者的地址都为中央仓库 htp://repo. mavel.org/ maven2,并且都关闭了 SNAPSHOT 的支持。这也就解释了为什么 Maven 默认就可以按需要从中央仓库下载构件。
<build>
<directory>${project.basedir}/target</directory>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
<finalName>${project.artifactId}-${project.version}</finalName>
<testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory>
<sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
<scriptSourceDirectory>${project.basedir}/src/main/scripts</scriptSourceDirectory>
<testSourceDirectory>${project.basedir}/src/test/java</testSourceDirectory>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
</resource>
</resources>
<testResources>
<testResource>
<directory>${project.basedir}/src/test/resources</directory>
</testResource>
</testResources>
</build>
这里依次定义了项目的主输出目录、主代码输出目录、最终构件的名称格式、测试代码输出目录、主源码目录、脚本源码目录、测试源码目录、主资源目录和测试资源目录。这就是 Maven 项目结构的约定。紧接着超级 POM 为核心插件设定版本。
<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) -->
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.3</version>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.8</version>
</plugin>
<plugin>
<artifactId>maven-release-plugin</artifactId>
<version>2.3.2</version>
</plugin>
</plugins>
</pluginManagement>
可以看到,超级 POM 实际上很简单,但从这个 POM 我们就能够知晓 Maven 约定的由来,不仅理解了什么是约定,为什么要遵循约定,还能明白约定是如何实现的。
4. 反应堆
在一个多模块的 Maven 项目中,反应堆(Reactor)是指所有模块组成的一个构建结构。对于单模块的项目,反应堆就是该模块本身,但对于多模块项目来说,反应堆就包含了各模块之间继承与依赖的关系,从而能够自动计算出模块构建顺序。
4.1 反应雄的构建序
实际的构建顺序是这样形成的: Maven 按序读取 POM,如果该 POM 没有依赖模块,那么就构建该模块,否则就先构建其依赖模块,如果该依赖还依赖于其他模块,则进一步先构建依赖的依赖。
4.2 裁剪反应雄
一般来说,用户会选择构建整个项目或者选择构建单个模块,但有些时候,用户会想要仅仅构建完整反应堆中的某些个模块。换句话说,用户需要实时地裁剪反应堆。
Maven 提供很多的命令行选项支持裁剪反应堆,输入 mvn -h 可以看到这些选项:
-am --also-make 同时构建所列模块的依赖模块口
-amd --also-make-dependents 同时构建依赖于所列模块的模块
-pl --projects 构建指定的模块,模块间用逗号分隔口
-rf --resume-from 从指定的模块回复反应堆
使用-pl选项指定构建某几个模块
mvn clean install -pl account-email account-persist
使用 -amd 选项可以同时构建依赖于所列模块的模块
mvn clean install -pl account-parent -amd
使用-rf选项可以在完整的反应堆构建顺序基础上指定从哪个模块开始构建
mvn clean install - rf account-email
06 Maven 聚合和继承的更多相关文章
- maven聚合与继承笔记
maven聚合 聚合的目的是为了快速构建项目,当我们有几个maven模块,想要一次性构建,而不是到每个模块下面去执行maven命令,这时候就需要使用maven聚合(或者称为多模块). 使用聚合的时候, ...
- (十四)Maven聚合与继承
1.Maven聚合 我们在平时的开发中,项目往往会被划分为好几个模块,比如common公共模块.system系统模块.log日志模块.reports统计模块.monitor监控模块等等.这时我们肯定会 ...
- Maven——聚合与继承
原文:http://www.cnblogs.com/xdp-gacl/p/4058008.html 一.聚合 如果我们想一次构建多个项目模块,那我们就需要对多个项目模块进行聚合 1.1.聚合配置代码 ...
- Maven聚合和继承的详细解释
说到聚合与继承我们都非常熟悉,maven相同也具备这种设计原则.以下我们来看一下Maven的pom怎样进行聚合与继承的配置实现. 一.为什么要聚合? 随着技术的飞速发展和各类用户对软件的要求越来越高. ...
- 笔记:Maven 聚合和继承
聚合模块 我们希望一次构建两个或更多项目,而不是到每个模块的目录下分别执行mvn命令,Maven 聚合这一特性就是为该需求服务的, 为了使用聚合,我们必须创建一个聚合模块,通过该模块与其他项目聚合,并 ...
- maven课程 项目管理利器-maven 3-10 maven聚合和继承 4星
本节主要讲了以下内容: 1 maven聚合 2 maven继承 1 maven聚合 <!-- 聚合特有标签 --> <groupId>com.hongxing</grou ...
- maven学习(十二)——maven聚合与继承实战
聚合与继承实战 创建四个Maven项目,如下图所示:
- Maven 教程(14)— Maven聚合与继承
原文地址:https://blog.csdn.net/liupeifeng3514/article/details/79553011 1.Maven聚合 我们在平时的开发中,项目往往会被划分为好几个模 ...
- Java开发学习(三十)----Maven聚合和继承解析
一.聚合 分模块开发后,需要将这四个项目都安装到本地仓库,目前我们只能通过项目Maven面板的install来安装,并且需要安装四个,如果我们的项目足够多,那么一个个安装起来还是比较麻烦的 如果四个项 ...
随机推荐
- django中使用Form组件
内容: 1.Form组件介绍 2.Form组件常用字段 3.Form组件校验功能 4.Form组件内置正则校验 参考:https://www.cnblogs.com/liwenzhou/p/87478 ...
- python编程之禅
在python界面输入 import this >>> import this The Zen of Python, by Tim Peters Beautiful is bette ...
- linux运维工程师工作中的一些常见问题解决方法
http://blog.sina.com.cn/s/blog_b9fe247a0101anoe.html 1.shell脚本死活不执行 问题:某天研发某同事找我说帮他看看他写的shell脚本,死活不执 ...
- 微信公众平台开发者认证,node
纯属分享 app.js var express = require('express'); var path = require('path'); var app = express(); ; var ...
- eclipse包层级显示和工作空间显示
本文两件事:设置包层级显示.设置工程的工作空间显示 一.各package包分层显示 平铺显示,实在不方便开发!也不方便查看工程包的层级结构,如下: 更换成层级显示: 二.工作空间显示 包用来区分类,工 ...
- Java 8 日期时间API
Java 8一个新增的重要特性就是引入了新的时间和日期API,它们被包含在java.time包中.借助新的时间和日期API可以以更简洁的方法处理时间和日期; 在介绍本篇文章内容之前,我们先来讨论Jav ...
- python 1 面向对象基础知识
1.编码范式 编程 是程序员用特定的 语法+数据结构+算法 组成的代码来告诉计算机如何执行任务的过程 如果把编程比作习武,编程方式就是武林中的各种流派,而在编程的世界里面最常见的两大流派是:面向过程 ...
- 使用JavaScript的XMLHttpRequest发送POST、GET请求以及接收返回值
使用XMLHttpRequest对象分为4部完成: 1.创建XMLHttpRequest组建 2.设置回调函数 3.初始化XMLHttpRequest组建 4.发送请求 实例代码: [javascri ...
- 主流JS库一览
主流JS库一览 标签: prototypedojomootoolsprototypejsjqueryjavascript 2009-10-14 22:52 19936人阅读 评论(2) 收藏 举报 ...
- 关于HTTP协议及SOCKET通信
一.HTTP 1.报文结构 HTTP:超文本传输协议,报文分为请求报文和响应报文. 2.端口(tomcat端口) http在熟知的80端口使用TCP的服务:tomcat的默认端口是8080 3.状态码 ...