maven实战 笔记

maven实战(三)——多模块项目的POM重构

1.重复

举个栗子

 1 <dependency>
 2   <groupId>org.springframework</groupId>
 3   <artifactid>spring-beans</artifactId>
 4   <version>2.5</version>
 5 </dependency>
 6 <dependency>
 7   <groupId>org.springframework</groupId>
 8   <artifactid>spring-context</artifactId>
 9   <version>2.5</version>
10 </dependency>
11 <dependency>
12   <groupId>org.springframework</groupId>
13   <artifactid>spring-core</artifactId>
14   <version>2.5</version>
15 </dependency>

代码有重复,version属性可以抽取出来,日后升级依赖版本的时候,只需要修改一处,而且也能避免漏掉升级某个依赖。

 1 <properties>
 2   <spring.version>2.5</spring.version>
 3 </properties>
 4 <depencencies>
 5   <dependency>
 6     <groupId>org.springframework</groupId>
 7     <artifactid>spring-beans</artifactId>
 8     <version>${spring.version}</version>
 9   </dependency>
10   <dependency>
11     <groupId>org.springframework</groupId>
12     <artifactid>spring-context</artifactId>
13     <version>${spring.version}</version>
14   </dependency>
15   <dependency>
16     <groupId>org.springframework</groupId>
17     <artifactid>spring-core</artifactId>
18     <version>${spring.version}</version>
19   </dependency>
20 </depencencies>

2.消除多模块依赖配置重复

举个栗子

考虑这样一个不大不小的项目,它有10多个Maven模块,这些模块分工明确,各司其职,相互之间耦合度比较小,这样大家就能够专注在自己的模块中进行开发而不用过多考虑他人对自己的影响。

我开始对模块A进行编码了,首先就需要引入一些常见的依赖如JUnit、Log4j等等:

 1  <dependency>
 2     <groupId>junit</groupId>
 3     <artifactid>junit</artifactId>
 4     <version>4.8.2</version>
 5     <scope>test</scope>
 6   </dependency>
 7   <dependency>
 8     <groupId>log4j</groupId>
 9     <artifactid>log4j</artifactId>
10     <version>1.2.16</version>
11   </dependency>

同事在开发模块B,他也要用JUnit和Log4j

 1  <dependency>
 2     <groupId>junit</groupId>
 3     <artifactid>junit</artifactId>
 4     <version>3.8.2</version>
 5   </dependency>
 6   <dependency>
 7     <groupId>log4j</groupId>
 8     <artifactid>log4j</artifactId>
 9     <version>1.2.9</version>
10   </dependency>

问题,同事漏了JUnit依赖的scope,而且版本也不一致

解决方法:使用继承机制以及dependencyManagement元素

dependencyManagement只会影响现有依赖的配置,但不会引入依赖

例如我们可以在父模块中配置如下:

 1 <dependencyManagement>
 2   <dependencies>
 3     <dependency>
 4       <groupId>junit</groupId>
 5       <artifactid>junit</artifactId>
 6       <version>4.8.2</version>
 7       <scope>test</scope>
 8     </dependency>
 9     <dependency>
10       <groupId>log4j</groupId>
11       <artifactid>log4j</artifactId>
12       <version>1.2.16</version>
13     </dependency>
14   </dependencies>
15 </dependencyManagement>

如果某个子模块需要使用JUnit和Log4j的时候,我们就可以简化依赖配置成这样:

1 <dependency>
2     <groupId>junit</groupId>
3     <artifactid>junit</artifactId>
4   </dependency>
5   <dependency>
6     <groupId>log4j</groupId>
7     <artifactid>log4j</artifactId>
8   </dependency>

在多模块Maven项目中,dependencyManagement几乎是必不可少的,因为只有它是才能够有效地帮我们维护依赖一致性。

可以把dependencyManagement放到单独的专门用来管理依赖的POM中,然后在需要使用依赖的模块中通过import scope依赖,就可以引入dependencyManagement。例如可以写这样一个用于依赖管理的POM:

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.juvenxu.sample</groupId>
  <artifactId>sample-dependency-infrastructure</artifactId>
  <packaging>pom</packaging>
  <version>1.0-SNAPSHOT</version>
  <dependencyManagement>
    <dependencies>
        <dependency>
          <groupId>junit</groupId>
          <artifactid>junit</artifactId>
          <version>4.8.2</version>
          <scope>test</scope>
        </dependency>
        <dependency>
          <groupId>log4j</groupId>
          <artifactid>log4j</artifactId>
          <version>1.2.16</version>
        </dependency>
    </dependencies>
  </dependencyManagement>
</project>

然后就可以通过非继承的方式来引入这段依赖管理配置:

 1  <dependencyManagement>
 2     <dependencies>
 3         <dependency>
 4           <groupId>com.juvenxu.sample</groupId>
 5           <artifactid>sample-dependency-infrastructure</artifactId>
 6           <version>1.0-SNAPSHOT</version>
 7           <type>pom</type>
 8           <scope>import</scope>
 9         </dependency>
10     </dependencies>
11   </dependencyManagement>
12
13   <dependency>
14     <groupId>junit</groupId>
15     <artifactid>junit</artifactId>
16   </dependency>
17   <dependency>
18     <groupId>log4j</groupId>
19     <artifactid>log4j</artifactId>
20   </dependency>

这样,父模块的POM就会非常干净,由专门的packaging为pom的POM来管理依赖,也契合的面向对象设计中的单一职责原则。此外,我们还能够创建多个这样的依赖管理POM,以更细化的方式管理依赖。这种做法与面向对象设计中使用组合而非继承也有点相似的味道。

3.消除多模块插件配置重复

使用pluginManagement元素管理插件。一个常见的用法就是我们希望项目所有模块的使用Maven Compiler Plugin的时候,都使用Java 1.5,以及指定Java源文件编码为UTF-8,这时可以在父模块的POM中如下配置pluginManagement:

 1 <build>
 2   <pluginManagement>
 3     <plugins>
 4       <plugin>
 5         <groupId>org.apache.maven.plugins</groupId>
 6         <artifactId>maven-compiler-plugin</artifactId>
 7         <version>2.3.2</version>
 8         <configuration>
 9           <source>1.5</source>
10           <target>1.5</target>
11           <encoding>UTF-8</encoding>
12         </configuration>
13       </plugin>
14     </plugins>
15   </pluginManagement>
16 </build>

这段配置会被应用到所有子模块的maven-compiler-plugin中,由于Maven内置了maven-compiler-plugin与生命周期的绑定,因此子模块就不再需要任何maven-compiler-plugin的配置了。

与依赖配置不同的是,通常所有项目对于任意一个依赖的配置都应该是统一的,但插件却不是这样,例如你可以希望模块A运行所有单元测试,模块B要跳过一些测试,这时就需要配置maven-surefire-plugin来实现,那样两个模块的插件配置就不一致了。这也就是说,简单的把插件配置提取到父POM的pluginManagement中往往不适合所有情况,那我们在使用的时候就需要注意了,只有那些普适的插件配置才应该使用pluginManagement提取到父POM中。

时间: 2024-10-13 17:44:27

maven实战 笔记的相关文章

《Maven实战》笔记-1-Maven使用入门

<Maven实战>徐晓斌 2011 机械工业出版社 一.介绍 1.名词 artifact:插件 极限编程XP 2.构建脚本: maven--pom.xml(Project Object Model) ant--build.xml 其基本结构是目标(target).依赖(depends),以及实现目标的任务. 3.maven vs ant Ant是过程式的,开发者显示指定每一个目标,以及完成该目标所需要执行的任务. Maven是声明式的,项目构建过程和过程各个阶段所需的工作都由插件实现. 4.相

学习笔记——Maven实战(九)打包的技巧

“打包“这个词听起来比较土,比较正式的说法应该是”构建项目软件包“,具体说就是将项目中的各种文件,比如源代码.编译生成的字节码.配置文件.文档,按照规范的格式生成归档,最常见的当然就是JAR包和WAR包了,复杂点的例子是Maven官方下载页面的分发包,它有自定义的格式,方便用户直接解压后就在命令行使用.作为一款”打包工具“,Maven自然有义务帮助用户创建各种各样的包,规范的JAR包和WAR包自然不再话下,略微复杂的自定义打包格式也必须支持,本文就介绍一些常用的打包案例以及相关的实现方式,除了前

学习笔记——Maven实战(十)Maven 3,是时候升级了

去年10月份Apache Maven发布了3.0正式版,而在上个月的22号,Eclipse基金会宣布了Eclipse 3.7(Indigo)的发布,该版本Eclipse最大的新特性之一就是集成了Maven.下载Eclipse IDE for Java Developers版本的用户会发现,Eclipse已经能够自动识别Maven项目了.Indigo中内置的Maven版本是3.0.2,这在一定程度上说明Maven 3已经非常稳定了.不过我相信一定还有很多Maven 2用户在犹豫是否升级,本文会介绍

学习笔记——Maven实战(五)自动化Web应用集成测试

自动化集成测试的角色 本专栏的上一篇文章讲述了Maven与持续集成的一些关系及具体实践,我们都知道,自动化测试是持续集成必不可少的一部分,基本上,没有自动化测试的持续集成,都很难称之为真正的持续集成.我们希望持续集成能够尽早的暴露问题,但这远非配置一个 Hudson/Jenkins服务器那么简单,只有真正用心编写了较为完整的测试用例,并一直维护它们,持续集成才能孜孜不倦地运行测试并第一时间报告问题. 自动化测试这个话题很大,本文不想争论测试先行还是后行,这里强调的是测试的自动化,并基于具体的技术

学习笔记——Maven实战(七)常用Maven插件介绍(上)

我们都知道Maven本质上是一个插件框架,它的核心并不执行任何具体的构建任务,所有这些任务都交给插件来完成,例如编译源代码是由maven-compiler-plugin完成的.进一步说,每个任务对应了一个插件目标(goal),每个插件会有一个或者多个目标,例如maven-compiler-plugin的compile目标用来编译位于src/main/java/目录下的主源码,testCompile目标用来编译位于src/test/java/目录下的测试源码. 用户可以通过两种方式调用Maven插

学习笔记——Maven实战(六)Gradle,构建工具的未来?

Maven面临的挑战 软件行业新旧交替的速度之快往往令人咂舌,不用多少时间,你就会发现曾经大红大紫的技术已经成为了昨日黄花,当然,Maven也不会例外.虽然目前它基本上是Java构建的事实标准,但我们也能看到新兴的工具在涌现,比如基于Goovy的Gradle,而去年Hibernate宣布从Maven迁移至Gradle这一事件更是吸引了不少眼球.在此之前,我也听到了不少对Maven的抱怨,包括XML的繁冗,不够灵活,学习曲线陡峭等等.那Gradle是否能够在继承 Maven优点的基础上,克服这些缺

hibernate实战笔记1---初探

由于在学习Spring的时候学到有关数据库的章节的时候,提及到了hibernate的集成,但是我对hibernate技术几乎是一点不了解,只是知道它是一个orm对象映射框架,所以在初探的章节做一下hibernate的简单了解,以及应用.顺便提一句,我用的是maven添加的hibernate开发包 简单使用hibernate的一般步骤 *创建并且编辑hibernate配置文件 该配置文件主要是用于链接数据库所用,定义了数据库的驱动程序和映射文件的位置,如下是一个简单的配置 <?xml versio

[Maven实战](9)传递性依赖

了解Spring的朋友都知道,创建一个Spring Framework项目都需要依赖什么样的Jar包.如果不使用Maven,那么在项目中就需要手动下载相关的依赖.由于Spring Framework又会依赖与其他开源类库,因此实际中往往会下载Spring Framework的jar包,还的下载所有它依赖的其他jar包.这么做往往就引入了很多不必要的依赖.另一种做法是只下载Spring Framework的jar包,不包含其他的相关依赖,到实际使用的时候,再根据报错信息,或者查询相关文档,加入需要

Maven学习笔记之——仓库(中)

Maven学习笔记之--仓库(中) 1.    远程仓库的配置 当出现默认的中央仓库无法满足我们的需求或者连接不上的时候.我们可以通过POM文件来指定远程仓库. <repositories> <repository> <id>jboss-maven2-release-repository</id> <name>JBoss Repository</name> <url>http://repository.jboss.org/