转自:https://yq.aliyun.com/ziliao/312160

在maven的管理体系中,各个项目组成了一个复杂的关系网,但是每个项目都是平等的,是个没有贵贱高低,众生平等的世界,全球每个项目从理论上来说都可以相互依赖。就是说,你跟开发Spring的大牛们平起平坐,你的项目可以依赖Spring项目,Spring项目也可以依赖你的项目(虽然现实中不太会发生,你倒贴钱人家也不敢引用)。

项目的依赖关系主要分为三种:依赖,继承,聚合

 

依赖关系

依赖关系是最常用的一种,就是你的项目需要依赖其他项目,比如Apache-common包,Spring包等等。

  1. <dependency>
  2. <groupId>junit</groupId>
  3. <artifactId>junit</artifactId>
  4. <version>4.11</version>
  5. <scope>test</scope>
  6. <type >jar</ type >
  7. <optional >true</ optional >
  8. </dependency>

任意一个外部依赖说明包含如下几个要素:groupId, artifactId, version, scope, type, optional。其中前3个是必须的。

这里的version可以用区间表达式来表示,比如(2.0,)表示>2.0,[2.0,3.0)表示2.0<=ver<3.0;多个条件之间用逗号分隔,比如[1,3],[5,7]。

type 一般在pom引用依赖时候出现,其他时候不用。

maven认为,程序对外部的依赖会随着程序的所处阶段和应用场景而变化,所以maven中的依赖关系有作用域(scope)的限制。在maven中,scope包含如下的取值:

Scope选项

compile(编译范围)

compile是默认的范围;如果没有提供一个范围,那该依赖的范围就是编译范围。编译范围依赖在所有的classpath中可用,同时它们也会被打包。

provided(已提供范围)

provided依赖只有在当JDK或者一个容器已提供该依赖之后才使用。例如,如果你开发了一个web应用,你可能在编译classpath中需要可用 的Servlet API来编译一个servlet,但是你不会想要在打包好的WAR中包含这个Servlet API;这个Servlet API JAR由你的应用服务器或者servlet容器提供。已提供范围的依赖在编译classpath(不是运行时)可用。它们不是传递性的,也不会被打包。

runtime(运行时范围)

runtime依赖在运行和测试系统的时候需要,但在编译的时候不需要。比如,你可能在编译的时候只需要JDBC API JAR,而只有在运行的时候才需要JDBC驱动实现。

test(测试范围)

test范围依赖在编译和运行时都不需要,它们只有在测试编译和测试运行阶段可用。

system(系统范围)

system范围依赖与provided类似,但是你必须显式的提供一个对于本地系统中JAR文件的路径。这么做是为了允许基于本地对象编译,而这些对象是系统类库的一部分。这样的构件应该是一直可用的,Maven也不会在仓库中去寻找它。 如果你将一个依赖范围设置成系统范围,你必须同时提供一个systemPath元素 。注意该范围是不推荐使用的(应该一直尽量去从公共或定制的Maven仓库中引用依赖)。

dependency中的type一般不用配置,默认是jar。当type为pom时,代表引用关系:

  1. <dependency>
  2. <groupId>org.sonatype.mavenbook</groupId>
  3. <artifactId>persistence-deps</artifactId>
  4. <version>1.0</version>
  5. <type>pom</type>
  6. </dependency>

此时,本项目会将persistence-deps的所有jar包导入依赖库。

可以创建一个打包方式为pom项目来将某些通用的依赖归在一起,供其他项目直接引用,不要忘了指定依赖类型为pom(<type>pom</type>)。

继承关系

继承就是避免重复,maven的继承也是这样,它还有一个好处就是让项目更加安全。项目之间存在上下级关系时就属于继承关系。

父项目的配置如下:

  1. <project>
  2. <modelVersion>4.0.0</modelVersion>
  3. <groupId>org.clf.parent</groupId>
  4. <artifactId>my-parent</artifactId>
  5. <version>2.0</version>
  6. <packaging>pom</packaging>
  7. <!-- 该节点下的依赖会被子项目自动全部继承 -->
  8. <dependencies>
  9. <dependency>
  10. <groupId>org.slf4j</groupId>
  11. <artifactId>slf4j-api</artifactId>
  12. <version>1.7.7</version>
  13. <type>jar</type>
  14. <scope>compile</scope>
  15. </dependency>
  16. </dependencies>
  17. <dependencyManagement>
  18. <!-- 该节点下的依赖关系只是为了统一版本号,不会被子项目自动继承,-->
  19. <!--除非子项目主动引用,好处是子项目可以不用写版本号 -->
  20. <dependencies>
  21. <dependency>
  22. <groupId>org.springframework</groupId>
  23. <artifactId>spring-orm</artifactId>
  24. <version>4.2.5.RELEASE</version>
  25. </dependency>
  26. <dependency>
  27. <groupId>org.springframework</groupId>
  28. <artifactId>spring-web</artifactId>
  29. <version>4.2.5.RELEASE</version>
  30. </dependency>
  31. <dependency>
  32. <groupId>org.springframework</groupId>
  33. <artifactId>spring-context-support</artifactId>
  34. <version>4.2.5.RELEASE</version>
  35. </dependency>
  36. <dependency>
  37. <groupId>org.springframework</groupId>
  38. <artifactId>spring-beans</artifactId>
  39. <version>4.2.5.RELEASE</version>
  40. </dependency>
  41. </dependencies>
  42. </dependencyManagement>
  43. <!-- 这个元素和dependencyManagement相类似,它是用来进行插件管理的-->
  44. <pluginManagement>
  45. ......
  46. </pluginManagement>
  47. </project>

注意,此时<packaging>必须为pom

为了项目的正确运行,必须让所有的子项目使用依赖项的统一版本,必须确保应用的各个项目的依赖项和版本一致,才能保证测试的和发布是相同的结果。

Maven 使用dependencyManagement 元素来提供了一种管理依赖版本号的方式。通常会在一个组织或者项目的最顶层的父POM 中看到dependencyManagement 元素。使用pom.xml 中的dependencyManagement 元素能让所有在子项目中引用一个依赖而不用显式的列出版本号。Maven 会沿着父子层次向上走,直到找到一个拥有dependencyManagement元素的项目,然后它就会使用在这个dependencyManagement 元素中指定的版本号。

父项目在dependencies声明的依赖,子项目会从全部自动地继承。而父项目在dependencyManagement里只是声明依赖,并不实现引入,因此子项目需要显示的声明需要用的依赖。如果不在子项目中声明依赖,是不会从父项目中继承下来的;只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且version和scope都读取自父pom另外如果子项目中指定了版本号,那么会使用子项目中指定的jar版本。

如果某个项目需要继承该父项目,基础配置应该这样:

  1. <project>
  2. <modelVersion>4.0.0</modelVersion>
  3. <groupId>org.clf.parent.son</groupId>
  4. <artifactId>my-son</artifactId>
  5. <version>1.0</version>
  6. <!-- 声明将父项目的坐标 -->
  7. <parent>
  8. <groupId>org.clf.parent</groupId>
  9. <artifactId>my-parent</artifactId>
  10. <version>2.0</version>
  11. <!-- 父项目的pom.xml文件的相对路径。相对路径允许你选择一个不同的路径。 -->
  12. <!--   默认值是../pom.xml。Maven首先在构建当前项目的地方寻找父项目的pom, -->
  13. <!--   其次在文件系统的这个位置(relativePath位置), -->
  14. <!--   然后在本地仓库,最后在远程仓库寻找父项目的pom。 -->
  15. <relativePath>../parent-project/pom.xml</relativePath>
  16. </parent>
  17. <!-- 声明父项目dependencyManagement的依赖,不用写版本号 -->
  18. <dependencies>
  19. <dependency>
  20. <groupId>org.springframework</groupId>
  21. <artifactId>spring-web</artifactId>
  22. </dependency>
  23. <dependency>
  24. <groupId>org.springframework</groupId>
  25. <artifactId>spring-beans</artifactId>
  26. </dependency>
  27. </dependencies>
  28. </project>

聚合关系

随着技术的飞速发展和各类用户对软件的要求越来越高,软件本身也变得越来越复杂,然后软件设计人员开始采用各种方式进行开发,于是就有了我们的分层架构、分模块开发,来提高代码的清晰和重用。针对于这一特性,maven也给予了相应的配置。

maven的多模块管理也是非常强大的。一般来说,maven要求同一个工程的所有模块都放置到同一个目录下,每一个子目录代表一个模块,比如

总项目/

pom.xml 总项目的pom配置文件

子模块1/

pom.xml 子模块1的pom文件

子模块2/

pom.xml子模块2的pom文件

总项目的配置如下:

  1. <project>
  2. <modelVersion>4.0.0</modelVersion>
  3. <groupId>org.clf.parent</groupId>
  4. <artifactId>my-parent</artifactId>
  5. <version>2.0</version>
  6. <!-- 打包类型必须为pom -->
  7. <packaging>pom</packaging>
  8. <!-- 声明了该项目的直接子模块 -->
  9. <modules>
  10. <!-- 这里配置的不是artifactId,而是这个模块的目录名称-->
  11. <module>module-1</module>
  12. <module>module-2</module>
  13. <module>module-3</module>
  14. </modules>
  15. <!-- 聚合也属于父子关系,总项目中的dependencies与dependencyManagement、pluginManagement用法与继承关系类似 -->
  16. <dependencies>
  17. ......
  18. </dependencies>
  19. <dependencyManagement>
  20. ......
  21. </dependencyManagement>
  22. <pluginManagement>
  23. ......
  24. </pluginManagement>
  25. </project>

子模块的配置如下:

  1. <project>
  2. <modelVersion>4.0.0</modelVersion>
  3. <groupId>org.clf.parent.son</groupId>
  4. <artifactId>my-son</artifactId>
  5. <version>1.0</version>
  6. <!-- 声明将父项目的坐标 -->
  7. <parent>
  8. <groupId>org.clf.parent</groupId>
  9. <artifactId>my-parent</artifactId>
  10. <version>2.0</version>
  11. </parent>
  12. </project>

继承与聚合的关系

首先,继承与聚合都属于父子关系,并且,聚合 POM与继承关系中的父POM的packaging都是pom。

不同的是,对于聚合模块来说,它知道有哪些被聚合的模块,但那些被聚合的模块不知道这个聚合模块的存在。对于继承关系的父 POM来说,它不知道有哪些子模块继承与它,但那些子模块都必须知道自己的父 POM是什么。

在实际项目中,一个 POM往往既是聚合POM,又是父 POM,它继承了某个项目,本身包含几个子模块,同时肯定会存在普通的依赖关系,就是说,依赖、继承、聚合这三种关系是并存的。

Maven可继承的POM 元素列表如下:

groupId :项目组 ID ,项目坐标的核心元素;

version :项目版本,项目坐标的核心元素;

description :项目的描述信息;

organization :项目的组织信息;

inceptionYear :项目的创始年份;

url :项目的 url 地址

develoers :项目的开发者信息;

contributors :项目的贡献者信息;

distributionManagerment:项目的部署信息;

issueManagement :缺陷跟踪系统信息;

ciManagement :项目的持续继承信息;

scm :项目的版本控制信息;

mailingListserv :项目的邮件列表信息;

properties :自定义的 Maven 属性;

dependencies :项目的依赖配置;

dependencyManagement:醒目的依赖管理配置;

repositories :项目的仓库配置;

build :包括项目的源码目录配置、输出目录配置、插件配置、插件管理配置等;

reporting :包括项目的报告输出目录配置、报告插件配置等。

9.Maven之(九)依赖关系的更多相关文章

  1. 查看maven项目的依赖关系 mvn dependency:tree

    maven-dependency-plugin最大的用途是帮助分析项目依赖,dependency:list能够列出项目最终解析到的依赖列表,dependency:tree能进一步的描绘项目依赖树,de ...

  2. maven install中依赖关系打包failed

    maven 中maven dependencies中依赖出现了项目,无法打包 ,出现的错误如图.说明:依赖的项目为project-dao  打包的项目为project-service  都在proje ...

  3. Maven之(九)依赖关系

    在maven的管理体系中,各个项目组成了一个复杂的关系网,但是每个项目都是平等的,是个没有贵贱高低,众生平等的世界,全球每个项目从理论上来说都可以相互依赖.就是说,你跟开发spring的大牛们平起平坐 ...

  4. 手动创建Maven项目并建立两个项目之间的依赖关系

    用命令行快速建立maven项目 -> mvn:archetype:generate -> 直接回车或者自己输入你想生成的 -> groupId ->artifactId -&g ...

  5. Maven之依赖关系

    在maven的管理体系中,各个项目组成了一个复杂的关系网,但是每个项目都是平等的,是个没有贵贱高低,众生平等的世界,全球每个项目从理论上来说都可以相互依赖.就是说,你跟开发Spring的大牛们平起平坐 ...

  6. maven项目,去除jar包中的不想要的依赖关系(Document root element "beans", must match DOCTYPE root "null". )

    maven dependencies中并不会删除 以下方法maven dependencies中并不会删除,可能程序引入的时候,会去掉这种依赖(猜的) 解释: 就是说项目中要用到某一个a.jar包,通 ...

  7. (原创) Maven查看JAR包的依赖关系

    如果是用命令行,可进入项目所在目录,然后输入: mvn dependency:tree ,来查看jar包依赖关系. 另外还可以在eclipse操作,如下图所示: 点击run后,开始输出JAR包依赖树. ...

  8. spring framework体系结构及内部各模块jar之间的maven依赖关系

    很多人都在用spring开发java项目,但是配置maven依赖的时候并不能明确要配置哪些spring的jar,经常是胡乱添加一堆,编译或运行报错就继续配置jar依赖,导致spring依赖混乱,甚至下 ...

  9. Intellij IDEA 中如何查看maven项目中所有jar包的依赖关系图(转载)

    Intellij IDEA 中如何查看maven项目中所有jar包的依赖关系图 2017年04月05日 10:53:13 李学凯 阅读数:104997更多 所属专栏: Intellij Idea   ...

随机推荐

  1. javaEE之-------统计站点刷新量

    每一个站点都有自己的统计訪问量,可是少不了server会出现意外情况,(如断电..) 所以就须要我们在站点挂机的前段时间将这个数据存起来. 我们就须要用到站点最大的容器,application,我们採 ...

  2. C++windows内核编程笔记day11 win32静态库和动态库的使用

    windows库程序: 静态库: 源码被链接到调用的程序或动态库,被调用时,代码最少有1份,文件后缀.LIB 动态库: 函数被程序或其它动态库调用,被调用时,代码仅仅有1份,文件后缀.DLL 静态库( ...

  3. 基于请求响应的MVC框架调用分析

    一.使用Servlet来处理请求响应 当client提交数据之后.接着发送请求,请求被封装成对象,server接收到请求,依据请求的URL.来推断将请求对象交由哪个Servlet处理. 在servle ...

  4. Linux下无需输入password自己主动登陆sshserver方法

    用OpenSSH在linux下登陆sshserver时.每次都提示要输入password,并且使用vim 的netrw插件编辑远程文件时每次改动后保存都要输password,很麻烦. 查看了netrw ...

  5. 关于HttpClient模拟浏览器请求的參数乱码问题解决方式

    转载请注明出处:http://blog.csdn.net/xiaojimanman/article/details/44407297 http://www.llwjy.com/blogdetail/9 ...

  6. 深入理解maven及应用(一):生命周期和插件

    在项目里用了快一年的maven了,近期突然发现maven项目在eclipse中build时很慢,由于经经常使用clean install命令来build项目,也没有管那么多,但近期实在受不了乌龟一样的 ...

  7. 圈复杂度(Cyclomatic Complexity)

    圈复杂度(Cyclomatic Complexity)是很常用的一种度量软件代码复杂程度的标准.这里所指的“代码复杂程度”并非软件内在业务逻辑的复杂程度,而是指代码的实现方式的 复杂程度.说起来有点绕 ...

  8. cf 864 F. Cities Excursions

    F. Cities Excursions There are n cities in Berland. Some pairs of them are connected with m directed ...

  9. 简单STL笔记

    想了好久,还是把自己了解的先整理一下吧,毕竟老是忘,这里主要简单介绍三种容器 set,queue,vector,以及栈 stack,队列queue 的简单用法.一.set 在set中,效率比vecto ...

  10. monyer教你玩电脑——CSS、HTML、JS、XML的关系

    首先Monyer还是有必要提一句:这是一篇低中等难度的文章.如果你是高手或被认为是高手,那么请pass掉这篇文章:如果你是新手,甚至不知道什么是css(譬如百度模版)等,那么请pass掉这篇文章.谢谢 ...