maven详解(二.Maven依赖(重点))

三、Maven依赖(重点)

maven管理依赖也就是jar包牛逼之处是不用我们自己下载,会从一些地方自动下载
maven远程仓库: https://mvnrepository.com/
maven远程仓库: https://maven.aliyun.com/mvn/search

maven工程中我们依靠在pom.xml文件进行配置完成jar包管理工作(依赖)
在工程中引入某个jar包,只需要在 pom.xml 中引入jar包的坐标,比如引入log4j的依赖:

<dependencies>
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>4.7</version>
		<scope>test</scope>
	</dependency>
</dependencies>

Maven 通过 groupIdartifactIdversion 三个向量来定位Maven仓库其jar包所在的位置,并把对应的jar包引入到工程中来。
jar包会自动下载,流程如下

1、依赖范围

了解、classpath是个什么东西
顾明思议,就是编译好的 class 文件所在的路径。
事实上,我们的类加载器( classloader )就是去对应的 classpath 中加在class二进制文件。
普通java项目
在这里插入图片描述

META-INF中有个文件,有以下内容,告诉jvm执行的时候去哪个类里找main方法。普通的java工程类路径就是最外层的目录。

Manifest-Version: 1.0
Main-Class: com.xinzhi.HelloUser

web项目
咱们的src打包后会放在
在这里插入图片描述
在这里插入图片描述
src目录下的配置文件会和class文件一样,自动copy到应用的 WEB-INF/classes目录下 ,所以普通jar包的类路径就是根路径,没有资源,如果有配置文件也放在src目录下,他会同步打包在类路径下。所以web项目的classpath是 WEB-INF/classes

maven项目
maven工程会将 src/main/javasrc/main/resources 文件夹下的文件全部打包在classpath中。运行时他们两个的文件夹下的文件会被放在一个文件夹下。
maven 项目不同的阶段引入到classpath中的依赖是不同的,例如,
编译时 ,maven 会将与编译相关的依赖引入classpath中
测试时 ,maven会将测试相关的的依赖引入到classpath中
运行时 ,maven会将与运行相关的依赖引入classpath中
而依赖范围就是用来控制依赖于这三种classpath的关系。
scope标签就是依赖范围的配置
该项默认配置compile,可选配置还有test、provided、runtime、system、import。
其中compile、test和provided使用较多,下面依次介绍。
有些jar包(如selvlet-api)运行时其实是不需要的,因为tomcat里有,但编译时是需要的,因为编译的时候没有tomcat环境
有些jar只在测试的时候才能用到。比如junit,真是运行不需要的
有些jar运行,测试时必须要有,编译时不需要,如jdbc驱动,编译时用的都是jdk中的接口,运行时我们才使用反射注册了驱动。
向以上的这些jar包不是说使用默认的compile一定不行,但是设置成合适的范围更好,当然有事会有问题,比如你引入的servlet-api和tomcat自带的不一样,就会出问题。

1.1 编译依赖范围(compile)

该范围就是默认依赖范围,此依赖范围对于编译、测试、运行三种 classpath 都有效,举个简单的例子,假如项目中有 fastjson 的依赖,那么 fastjson 不管是在编译,测试,还是运行都会被用到,因此 fastjson 必须是编译范围(构件默认的是编译范围,所以依赖范围是编译范围的无须显示指定)

<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>fastjson</artifactId>
	<version>1.2.68</version>
</dependency>

1.2 测试依赖范围(test)

使用此依赖范围的依赖,只对测试classpath有效,在编译主代码和项目运行时,都将无法使用该依赖,最典型的例子就是 Junit, 构件在测试时才需要,所以它的依赖范围是测试,因此它的依赖范围需要显示指定为、、test,当然不显示指定依赖范围也不会报错,但是该依赖会被加入到编译和运行的classpath中,造成不必要的浪费 。

<dependency>
	<groupId>junit</groupId>
	<artifactId>junit</artifactId>
	<version>4.7</version>
	<scope>test</scope>
</dependency>

1.3 已提供依赖范围(provided)

使用该依赖范围的maven依赖,只对编译和测试的classpath有效,对运行的classpath无效,典型的例子就是servlet-api, 编译和测试该项目的时候需要该依赖,但是在运行时,web容器已经提供的该依赖,所以运行时就不再需要此依赖,如果不显示指定该依赖范围,并且容器依赖的版本和maven依赖的版本不一致的话,可能会引起版本冲突,造成不良影响。

<dependency>
	<groupId>javax.servlet</groupId>
	<artifactId>javax.servlet-api</artifactId>
	<version>4.0.1</version>
	<scope>provided</scope>
</dependency>

1.4 运行时依赖范围(runtime)

使用该依赖范围的maven依赖,只对测试和运行的classpath有效,对编译的classpath无效,典型例子就是JDBC的驱动实现,项目主代码编译的时候只需要JDK提供的JDBC接口,只有在测试和运行的时候才需要实现上述接口的具体JDBC驱动。

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.25</version>
<scope>runtime</scope>
</dependency>

其他的范围不常用,有兴趣自己研究

2、依赖的传递

jar其实也是别人写的工程,他也会依赖其他的jar包,传递性让我们可以不用关系我们所依赖的jar他依赖了哪些jar,只要我们添加了依赖,他会自动将他所依赖的jar统统依赖进来。
在这里插入图片描述

我们只需依赖A.jar,其他的会自动传递进来。
依赖传递的原则:
最短路径优先原则:如果A依赖于B,B依赖于C,在B和C 中同时有log4j的依赖,并且这两个版本不一致,那么A会根据最短路径原则,在A中会传递过来B的log4j版本。
在这里插入图片描述

路径相同先声明原则:如果我们的工程同时依赖于B和A,B和C没有依赖关系,并且都有D的依赖,且版本不一致,那么会引入在pom.xml中先声明依赖的log4j版本。
在这里插入图片描述

<dependency>
	<groupId>com.xxxx</groupId>
	<artifactId>B</artifactId>
	<version>1.5.3</version>
</dependency>
<dependency>
	<groupId>com.xxxx</groupId>
	<artifactId>A</artifactId>
	<version>1.12.2</version>
</dependency>

因为1.2.3先声明,所以获胜。
特别注意:
不同版本的jar选一个会导致一个问题,1.3.2版本高,A.jar可能用到了高版本的一些新的方法,此时因为某些原因系统选择了低版本,就会导致A.jar报错,无法运行。那么就要想办法把低版本排除掉,一般高版本会兼容低版本。

3、依赖的排除

结合上个例子,我们想把低版本的D.jar排除了,就可以这样做,这样系统就只能依赖高版本

<dependencies>
<dependency>
	<groupId>com.xxxx</groupId>
	<artifactId>B</artifactId>
	<version>1.5.3</version>
<exclusions>
<exclusion>
	<artifactId>com.xxxx</artifactId>
	<groupId>D</groupId>
</exlcusion>
</exclusions>
</dependency>
<dependency>
	<groupId>com.xxxx</groupId>
	<artifactId>A</artifactId>
	<version>1.12.2</version>
</dependency>

4、聚合和继承

分布式开发必须要用
在这里插入图片描述

聚合模块(父模块)的打包方式必须为pom,否则无法完成构建。
在聚合多个项目时,如果这些被聚合的项目中需要引入相同的Jar,那么可以将这些Jar写入父pom中,各个子项目
继承该pom即可。,父模块的打包方式必须为pom,否则无法构建项目。
通过在各个子模块中配置来表明其继承与哪一个父模块:

</dependencies>
	<parent>
	<artifactId>parent</artifactId>
	<groupId>org.example</groupId>
	<version>1.0-SNAPSHOT</version>
	</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>childern-two</artifactId>

可以被继承的POM元素如下:
groupId:项目组ID,项目坐标的核心元素
version:项目版本,项目坐标的核心因素
properties:自定义的Maven属性 一般用于同一制定各个依赖的版本号
dependencies:项目的依赖配置 公共的依赖
dependencyManagement:项目的依赖管理配置
repositories:项目的仓库配置
build:包括项目的源码目录配置、输出目录配置、插件配置、插件管理配置等
一些对项目的描述
description:项目的描述信息
organization:项目的组织信息
inceptionYear:项目的创始年份
url:项目的URL地址
developers:项目的开发者信息
contributors:项目的贡献者信息
distributionManagement:项目的部署配置
issueManagement:项目的缺陷跟踪系统信息
ciManagement:项目的持续集成系统信息
scm:项目的版本控制系统
malilingLists:项目的邮件列表信息
reporting:包括项目的报告输出目录配置、报告插件配置等

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值