《Maven实战》读书笔记 —— Maven坐标和依赖

Posted flyingweb

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《Maven实战》读书笔记 —— Maven坐标和依赖相关的知识,希望对你有一定的参考价值。

第四章:坐标和依赖

正如第1章所述,Maven的一大功能是管理项目依赖。为了能自动化地解析任何一个Java构件,Maven就必须将它们唯一标识,这就是依赖管理的底层基础——坐标

4.1 何为Maven坐标

关于坐标(Coordinate),大家最熟悉的定义应该来自于立体几何。在一个立体坐标系中,该立体空间内的任何一个点,都能够用坐标(x,y,z)唯一标识。在实际生活中,我们可以将地址看成一种坐标。省市县等一系列信息同样可以唯一标识城市中的任一居住地址,邮局和快递公司正是基于这样一种坐标进行邮件寄送的。

对应于几何中的点和城市中的地址,Maven世界中拥有数量非常巨大的构件(如jar),在Maven为这些构件引入坐标概念之前,我们无法使用任何一种方式来唯一标识所有这些构件。因此,当需要用到Spring Framework依赖的时候,大家会去Spring Framework网站寻找,当需要用到log4j依赖的时候,大家又会去Apache网站寻找。又因为各个项目的网站风格迥异,大量的时间花费在了搜索、浏览网页和下载构件。Maven定义了这样的一组规则:世界上任何一个构件都可以使用Maven坐标唯一标识,Maven坐标的元素包括GroupId、artfactId、version、packaging、classifier,现在只要我们提供正确的坐标,Maven就能够帮助我们找到对应的构件。

也许你会奇怪,“Maven是从哪里下载构件呢?”答案很简单,Maven内置了一个中央仓库地址(http://repo1.maven.org/maven2),该中央仓库包含了世界上大部分流行的开源项目构件,Maven会在需要的时候去那里下载。

在我们开发Maven项目的时候,也需要定义适当的坐标,这是Maven强制要求的。在这个基础上,其它的Maven项目才能引用该项目生成的构件。

4.2 坐标详解

Maven坐标为各种构件引入了秩序,任何一个构件都必须明确定义自己的坐标,而一组Maven坐标是通过一些元素定义的,它们是GroupId、artfactId、version、packaging、classifier。坐标定义如下:

<groupId>org.sonatype.nexus</groupId>
<artifactId>nexus-indexer</artifactId>
<version>2.0.0</version>
<packaging>jar</packaging>
  • groupId:定义当前Maven项目所属的实际项目。首先,Maven项目和实际项目不一定是一对一的关系。比如SpringFramework这一实际项目,其对应的Maven项目会有很多,如spring-core、spring-context等。这是由于Maven中模块的概念,因此一个实际项目往往会被划分为很多模块。推荐的做法是使用项目隶属的组织或公司的反向域名作为前缀,后跟实际项目名称。上例中,GroupId为org.sonatype.nexus,org.sonatype表示Sonatype公司建立的一个非营利性组织,nexus表示Nexus这一实际项目。
  • artifactId:定义实际项目中的一个Maven项目模块,推荐的做法是使用实际项目名称作为前缀,后跟模块名称。上例中,artfactId是nexus-indexer,使用了实际项目名nexus作为前缀,这样做的好处是方便寻找实际构件。默认情况下,Maven生成的构件,其文件名会以artfactId作为开头
  • version:定义Maven项目当前所处的版本,如上例中nexus-indexer的版本是2.0.0。
  • packaging:定义项目的打包方式。首先,打包方式通常于所生成构件的文件扩展名对应,如上例中packaging为jar,最终的文件名为nexus-indexer-2.0.0.jar。其次,打包方式会影响到构件的生命周期。
  • classifier:该元素用来帮助定义构建输出的一些附属构件。附属构件与主构件对应,如上例中的主构件是nexus-indexer-2.0.0.jar,该项目可能还会用过使用一些插件生成nexus-indexer-2.0.0-javadoc.jar、nexus-indexer-2.0.0-sources.jar这样一些附属构件,其中包含了Java文档和源代码。这时候,javadoc和sources就是这两个附属构件的classifier。这样附属构件也就拥有了自己唯一的坐标。

上述的5个元素中,groupId、artfactId、version是必须定义的,packaging是可选的(默认的打包方式的jar),而classifier是不能直接定义的。

4.3 依赖的配置

一个依赖的声明可以包含如下的一些元素:

<project>
  ......

  <dependencies>
  	<dependency>
  		<groupId>org.springframework</groupId>   //项目名称(依赖的基本坐标)
  		<artifactId>spring-core</artifactId>     //模块名称(依赖的基本坐标)
  		<version>2.5.6</version>                 //所处版本(依赖的基本坐标)
                <type>...</type>                         //打包类型(默认jar)
                <scope>...</scope>                       //依赖范围(默认compile)
                <optional>...</optional>                 //依赖是否可选
                <exclusions>                             //排除传递性依赖
                      <exclusion>...</exclusion>
                </exclusions>
  	</dependency>
  </dependencies>
  ......
</project>                                        

4.4 依赖范围

Maven在编译项目主代码的时候需要使用一套classpath,Maven在编译和执行测试的时候会使用一套classpath,Maven在实际运行项目的时候会使用一套classpath。依赖范围就是用来控制依赖与classpath(编译classpath、测试classpath、运行classpath)的关系:

  • compile:编译依赖范围(默认)。使用此依赖范围的Maven依赖,对于编译、测试、运行三种classpath都有效。
  • test:测试依赖范围。使用此依赖范围的Maven依赖,只对测试classpath有效,在编译主代码或者运行项目的时候将无法使用此类依赖。典型的例子是JUnit,它只有在编译测试代码及运行测试的时候才需要。
  • provided:已提供依赖范围。使用此依赖范围的Maven依赖,对于编译和测试classpath有效,但是在运行时无效。典型的例子是servlet-api,编译和测试项目的时候需要该依赖,但是在运行项目的时候,由于容器已经提供,就不需要Maven重复引入。
  • runtime:运行时依赖范围。使用此依赖范围的Maven依赖,对于测试和运行classpath有效,但在编译主代码时无效。典型的例子是JDBC驱动实现,项目主代码的编译只需要JDK提供JDBC接口,只有在执行测试和运行项目的时候才需要实现上述接口的具体JDBC驱动。
  • system:系统依赖范围。使用此依赖范围的Maven依赖,和provided依赖范围一致。但是使用system范围时必须通过systemPath元素显式地指定依赖文件的路径。由于此类依赖不是通过Maven仓库解析的,而且往往于本机系统绑定,可能造成构件的不可移植,因此应该慎重使用。
  • import(Maven 2.0.9及以上):导入依赖范围。该依赖范围不会对三种classpath产生实际的影响【后续完善】。

4.5 传递性依赖

4.5.1 何为传递性依赖

 

以上是关于《Maven实战》读书笔记 —— Maven坐标和依赖的主要内容,如果未能解决你的问题,请参考以下文章

读书笔记《Maven实战》第6章 仓库

读书笔记——《Maven实战》

Maven实战读书笔记:Maven概述

《Maven实战》读书笔记 —— Maven简介

Maven实战读书笔记:Maven灵活构建

Maven实战读书笔记:Maven生命周期与插件