maven实战总结——3-5章坐标与依赖

pom文件概要

mvn项目的核心是pom.xml文件,定义了项目的基本信息,用于描述项目如何构建和声明项目依赖等。该文件位于项目的根目录下。

pom文件的基本元素

<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">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.xuming.mvnbook</groupId>
  <artifactId>hello-world</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>hello-world</name>
</project>
  1. pom的根元素为project
  2. 根元素下的第一个元素是modelVersion,指定了模型的版本,对于mvn2和mvn3来说只能是4.0.0
  3. groupId定义了项目的所属组,往往是公司+具体的项目,因为一个公司可能有多个项目;如 org.apache.hbase;apache的hbase项目
  4. artifactId 定义了当前项目在公司中的唯一id ,一般使用项目名+模块名 如:hbase-client;hbase下的client模块。
  5. version指定了项目的当前版本 如1.0-SNAPSHOT ;2.0等等
  6. name 声明了一个对于用户更为友好的项目名称,这个元素不是必须的。

mvn项目的目录结构规范

–src/main/java 项目的主代码目录
–src/main/sources 项目的资源文件目录
–src/test/java 项目的测试代码目录
–src/test/sources 项目的测试资源文件目录

mvn坐标

mvn的坐标为构建引入了秩序,任何一个构建都必须明确自己的坐标。而一组坐标是通过一系列的元素定义的,groupId、artifactId、version、packaging、classifier

  1. groupId定义了项目的所属组,往往是公司+具体的项目,因为一个公司可能有多个项目;如 org.apache.hbase;apache的hbase项目
  2. artifactId 定义了当前项目在公司中的唯一id ,一般使用项目名+模块名 如:hbase-client;hbase下的client模块。
  3. version指定了项目的当前版本 如1.0-SNAPSHOT ;2.0等等
  4. packaging 定义了构建的打包方式,默认为jar
  5. classifier 定义构建输出的附属构建,附属构建与主构件对应,如主构件为nexus-indexer-2.0.0.jar,改项目可能通过一些其他的插件生成nexus-indexer-2.0.0-javadoc.jar、nexus-indexer-2.0.0-sources.jar这样的附属构建,对于nexus-indexer-2.0.0.jar,对应的sources和doc就是其附属构建。注意不能直接定义项目的附属构建,因为附属构建不是项目默认生成的,而是由附加的插件帮助生成的。

以上5个元素groupId、artifactId、version是必须的,packaging是可选的(默认为jar)classifier是不能直接定义的。

mvn依赖

一个基本的依赖会包含groupId、artifactId、version等元素的组成,其实一个依赖可以包含如下的元素;

<dependencies>
	<dependency>
			<groupId>...</groupId>
			<artifactId>...<artifactId>
			<version>...</version>
			<type>...</type>
			<scope>...</scope>
			<optional>...</optional>
			<exclusions>
					<exclusions>
					<exclusions>
			</exclusions>
	</dependency>
</dependencies>
  • groupId、artifactId、version 是基本的依赖坐标,对于任何依赖来说,坐标都是最重要的,只有通过坐标才能定位一个唯一的构建

  • type 依赖类型,对应于项目定义的packaging,大部分情况下不需要配置,默认为jar

  • scope 依赖的范围

  • optional 表示是否为可选的依赖

  • exclusions 用来排出传递性依赖。

    依赖范围 scope

    依赖范围就是用来控制依赖与三种时期classpath(编译时classpath、测试时classpash、运行时classpath)的关系的,
    maven支持的依赖范围:

  • compile:编译依赖范围。默认是此依赖范围。此依赖范围对于三个时期的classpath都有效

  • test 依赖范围;此依赖范围指定测试的classpath有效,典型的样例为JUnit,

  • provided 以提供依赖范围;此依赖范围指定编译和测试有效,运行时无效,典型的样例为servlet-api

  • runtime 运行时依赖范围; 对于测试和运行时有效,编译时期无效 JDBC驱动

  • system 系统依赖范围;此依赖范围classpath作用与provider一致;但是此范围必须显示的通过systemPath指定依赖文件的路径,由于此依赖不是通过maven仓库解析的,而且与本机系统绑定,造成不可移植,应该谨慎使用。

  • import 导入依赖范围;此依赖范围不会对三种classpath造成影响。模块化的时候使用此依赖范围。

依赖范围scope编译classpath测试classpath运行classpath例子
compileYYYspring-core
test-Y-Junit
providerYY-servlet-api
runtime-YYJDBC驱动
systemYY-本地的,MVN库之外的文件

依赖传递

当我们的项目使用spring-core.jar 时,如果我们不使用mvn,如果spring-core有其他的依赖,我们需要手动的去网上下载spring-core.jar的依赖,然后手动的将其添加的classpath中,有了mvn后,不再需要这么做,mvn会去中央仓库去找spring-core的构建(spring-core-version.pom),会将其依赖自动的导入到我们的项目中。

传递性依赖和依赖范围

依赖范围不仅可以控制依赖与三种classpath的关系,还可以影响传递性依赖。
假设A依赖B、B依赖C;我们说A对于B是第一直接依赖;B对于C是第二直接依赖;A对于C是传递依赖。第一直接依赖范围和第二直接依赖范围决定了传递依赖的范围
如下图:最左边一列表示第一直接依赖;第一行表示第二直接依赖,中间单元格为传递依赖范围

compiletestprovidedruntime
compilecompile--runtime
testtest--test
providedprovided-providedprovided
runtimeruntime--runtime

总结:

  1. 当第二直接依赖为compile时候,传递依赖于第一直接依赖一致
  2. 当第二依赖为test的时候,依赖不会传递
  3. 当第二依赖为provided的时候,只有第一依赖为provided时才会传递,且传递范围为provided、
  4. 当第二依赖为runtime的时候 ,传递范围与第一依赖一致;但第一依赖为compile时除外,此时的传递范围为runtime

依赖调节

mvn引入传递依赖机制,简化了依赖声明,大部分时候,我们只需要关注项目直接依赖了什么,不需要关注间接依赖,但依赖出现问题的时候,我们需要知道该传递依赖是从哪个路径引入的。
例如:A->B->C->X(1.0) A->D->X(2.0),X是A的传递依赖,但是两个依赖的X版本不一致。
mvn 依赖调节的两个原则:

  1. 路径最短原则 例如以上例子 X2.0会被传递依赖
  2. 第一声明者优先原则;当路径一致时,使用此原则

如果默认的调节方式不能满足项目的需求,我们可以使用排出依赖,既将传递的依赖exclusions 出去之后定义自己的依赖。

最佳实践

  • 归类依赖,我们可以使用定义properties的方式,将依赖的版本抽象出来,当依赖需要升级的时候,只需要修改properties即可,
  • 依赖查询相关命令
mvn dependency:list  查询当前项目的已解析依赖
mvn dependency:tree  查询当前项目的已解析依赖树
mvn dependency:analyze  依赖分析
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值