maven依赖管理(依赖范围专篇)~我的依赖我来管

依赖范围

背景

首先为什么maven要在依赖中存在一个< scope > 呢?主要解决两个问题,第一就是我们的依赖可以通过我们的决定:编译、测试、打包的时候是否需要这个依赖。第二个就是依赖的传递问题,例如:我们的项目依赖B,B有一个测试依赖,对我们而言,不需要。所以就可以通过设置依赖的范围,来解决传递的问题。

理解

依赖范围< scope >值为:compile(编译)、test(测试)、provided(提供依赖)、runtime(运行时依赖)、system(系统依赖)、import(导入)。主要区别在于classpath。maven中有三种 classpath:编译classpath、测试classpath、运行classpath。

classpath理解

什么是classpath呢,我们肯定经常遇到这个单词,我们今天来搞定它。首先,我们来打包一个maven项目看一下。

在这里插入图片描述
我们都知道idea(所有的编辑器)显示的目录都不是我们项目打包对应的目录。在maven项目中,target才是我们项目的真实目录。我们可以看到classes目录下存放的我们的源码包和静态文件index.html。其实classpath指的就是classes目录,测试有自己的test-classes目录。然后我们在看一下我们打成的jar包。
在这里插入图片描述
从这里可以看出,jar中包含三部分信息,打包信息,源码,静态文件。

打包信息查看

在这里插入图片描述
基础jar包信息,Mainfest-Version:是一个版本声明,Archiver-version:存档版本,Built-By:构建作者,Created-By:用什么工具创建的(还可以是ant等),Build-Jdk:构建时使用的JDK版本。
在这里插入图片描述

查看maven打包信息

在这里插入图片描述pom.xml
这里就是我们项目中的pom.xml 文件
pom.properties
自动生成的一些项目的信息。
在这里插入图片描述
所以,classpath 指的就是项目打包的根目录,可知测试的目录是不进行打包的。
好了我们来继续说< scope >,根据值要一个一个分析。


compile(编译)

编译依赖范围,也是依赖的范围的默认值。即编译classpath、测试classpath、运行classpath 都有效,也可以进行依赖的传递。举一个例子:比如spring-core,无论使我们编译,测试,执行都需要使用到这个依赖。所以设置范围为compile。


test(测试)

测试依赖范围,此范围只对测试classpath生效。是不进行依赖传递的,举一个例子:Junit。我们只会在测试的时候使用到这个依赖。而且,当我们依赖一个组件的时候,一般情况下,并不希望把此组件的测试案例引用过来。所以不支持传递。


provided(提供)

提供依赖范围,对编译和测试的classpath都有效,但在运行时无效。举一个例子:servlet-api。很多人还搞不清楚servlet-api和tomcat的区别。servlet-api相当于sun公司定义的一套应用服务器(或者中间件)的一套规范。tomcat相当于是servlet-api的实现。servlet-api的实现还有 jetty、JBoss等。通常我们在编写web项目的时候都会打包成一个war包,然后丢进tomcat中运行。当然如果我们直接创建的web项目,编译器会自动帮我依赖servlet-api,我们通常没有察觉。但是我们在编写单纯maven项目的时候,通常是找不到servlet的,这个时候我们就需要添加servlet-api,不然就会报红,且无法编译我们的项目。但是我们运行的时候又不需要我们自己导入的servlet-api的依赖,因为tomcat中已经存在了,所以我们这个时候就需要配置成provided。如果没有看明白,说明你需要搞清楚,什么是IDEA帮我们做的事情,什么是我们自己做的事情。编写java项目完全可以只是用记事本来进行编码的。


runtime (运行)

运行时依赖范围,对于编译和测试classpath无效,只对运行时classpath有效。举一个例子:JDBC驱动的实现。因为jdk默认为我们提供了JDBC的API,所以我们在编码的时候根本就不去调用JDBC的驱动,但是在运行的时候需要JDBC的驱动。于是我们可以设置JDBC的驱动为运行时。


system(系统)

系统依赖范围,依赖关系与provided一致,但是使用system 范围的依赖时必须通过systemPath 元素显式地指定依赖文件的路径。由于此类依赖不是通过maven仓库解析,而且往往与本机系统绑定,可以能造成构建的不可移植性,因此应该谨慎使用。例如:

<dependency>
        <groupId>javax.sql</groupId>
        <artifactId>jdbc-stdext</artifactId>
        <version>2.0</version>
        <scope>system</scope>
        <systemPath>${java.home}/lib/rt.jar</systemPath>
    </dependency>

import (导入)

导入依赖范围,这个依赖不会对三种classpath产生实际的影响。但是这个应该是怎么用的呢?都知道我们的父类pom 一般会定义< dependencyManagement >来管理我们的依赖。通过import我们可以把其他类中的< dependencyManagement >引用过来。这有什么好处呢?比如我们的项目很大的时候,通常会有我们自己编写的构件和第三方的构件,这个方便管理我们就可以分别单独通过一个pom项目来管理这个构件的版本。

总结

最后,来一张表格进行一下总结。

依赖范围编译classpath测试classpath运行classpath例子
compileYYYspring-core
testYJUnit
providedYYservlet-api
runtimeYYJDBC驱动实现
systemYY本地的,maven仓库之外的类库文件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值