一篇文章带你了解Maven的坐标概念以及依赖管理

目录
  • 1、什么是坐标?
    • ①、数学中的坐标
    • ②、Maven 中的坐标
    • ③、Maven 坐标和仓库,jar 包的关系
  • 2、什么是依赖?
  • 3、依赖的详细配置
  • 4、依赖的范围 scope
    • 1、compile 范围依赖
    • 2、test 范围依赖
    • 3、provided 范围依赖
    • 4、runtime 范围依赖:
  • 5、依赖的传递
    • 我们这里举个例子来看:
      • ①、第二依赖范围是 test
      • ②、第二依赖范围是 compile
  • 6、依赖的排除
  • 7、依赖的冲突
  • 8、可选依赖
  • 总结

1、什么是坐标?

①、数学中的坐标

在平面上,使用 X 、Y 两个向量可以唯一的定位平面中的任何一个点

在空间中,使用 X、Y、Z 三个向量可以唯一的定位空间中的任意一个点

②、Maven 中的坐标

俗称 gav:使用下面三个向量子仓库中唯一定位一个 Maven 工程

在项目中的 pom.xml 文件中,我们可以看到下面gav的定义:

1、groupid:公司或组织域名倒序

<groupid>com.ys.maven</groupid>

2、artifactid:模块名,也是实际项目的名称

<artifactid>Maven_05</artifactid>    

3、version:当前项目的版本      

<version>0.0.1-SNAPSHOT</version>

③、Maven 坐标和仓库,jar 包的关系

什么是仓库,后面我们会详细讲解,现在你只需要知道是Maven 用来存放 jar 包的地方。

那么依照上面定义的 gav,我们执行 mvn -install 命令,会出现什么情况呢?

首先进入到我们第二篇博客 Maven 的安装配置,通过 settings.xml 文件配置的仓库目录。

将我们上面配置的 gav 向量组合起来就是目录:

com/ys/maven/Maven_05/0.0.1-SNAPSHOT/Maven_05-0.0.1-SNAPSHOT.jar

其次,我们观察打出来的 jar 包:

Maven_05-0.0.1-SNAPSHOT.jar

也就是 artifactid-version.jar

2、什么是依赖?

什么是 依赖?相信有过一定开发经验的人知道,每当我们需要使用某个框架时,比如 SpringMVC,那么我们需要导入相应的 jar 包,但是手动导入包的时候,往往会漏掉几个 jar 包,那么在使用该框架的时候系统就会报错。那么我们就说导入的包与未导入的包存在依赖关系。而使用 Maven,我们只需要在 pom.xml 文件中进行相应的配置,它就会帮助我们自动管理 jar 包之间的依赖关系。那么它是怎么管理的呢,接下来我们会详细讲解。

3、依赖的详细配置

我们以 Junit 为例,在 pom.xml 文件中进行详细而完整的配置。 

<project>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <type>...</type>
            <scope>...</scope>
            <optional>...</optional>
            <exclusions>
                <exclusion>
                  <groupId>...</groupId>
                  <artifactId>...</artifactId>
                </exclusion>
          </exclusions>
        </dependency>
      </dependencies>
</project>

①、dependencies:一个 pom.xml 文件中只能存在一个这样的标签。用来管理依赖的总标签。

②、dependency:包含在dependencies标签中,可以有无数个,每一个表示一个依赖

③、groupId,artifactIdversion:依赖的基本坐标,对于任何一个依赖来说,基本坐标是最重要的,Maven根据坐标才能找到需要的依赖。

④、type:依赖的类型,对应于项目坐标定义的packaging。大部分情况下,该元素不必声明,其默认值是jar。

⑤、scope:依赖的范围,默认值是 compile。后面会进行详解。

⑥、optional:标记依赖是否可选。

⑦、exclusions:用来排除传递性依赖,后面会进行详细介绍。

4、依赖的范围 scope

一般情况下,我们对前面三个依赖用的比较多。下面的主程序表示maven 目录结构 src/main/java.测试程序目录结构为:src/test/java

1、compile 范围依赖

对主程序是否有效:有效

对测试程序是否有效:有效

是否参与打包:参与

是否参与部署:参与

典型例子:log4j

2、test 范围依赖

对主程序是否有效:无效

对测试程序是否有效:有效

是否参与打包:不参与

是否参与部署:不参与

典型例子:Junit

3、provided 范围依赖

对主程序是否有效:有效

对测试程序是否有效:有效

是否参与打包:不参与

是否参与部署:不参与

典型例子:servlet-api.jar,一般在发布到 服务器中,比如 tomcat,服务器会自带 servlet-api.jar 包,所以provided 范围依赖只在编译测试有效。   

4、runtime 范围依赖:

在测试、运行的时候依赖,在编译的时候不依赖。例如:JDBC驱动,项目代码只需要jdk提供的jdbc接口,只有在执行测试和运行项目的时候才需要实现jdbc的功能。  

接下来我们举几个例子在工程中实际去理解:

test 依赖和 compile 依赖的区别:

①、首先我们在 pom.xml 文件中配置,Junit 的 test 依赖      

②、我们在主程序中去导入 Junit 的包,然后进行 mvn -compile 编译,很明显,test 范围的在主程序中无效,故编译会报错。

我们在src/main/java 包下新建 MavenTest.java,并导入 Junit 包

然后执行 mvn -compile 操作,如下图报错信息:

③、我们将 Junit 的依赖范围改为 compile,然后执行 mvn -compile

发现 mvn -compile 没有报错了。

5、依赖的传递

比如我们创建三个Maven 工程,maven-first,maven-second以及maven-third,而third依赖于second,second又依赖于first,那么我们说 second是 third 的第一直接依赖,first是second的第二直接依赖。而first是third的间接依赖。

依赖之间的传递如下图:第一列表示第一直接依赖,第一行表示第二直接依赖

总结:

1、当第二依赖的范围是compile的时候,传递性依赖的范围与第一直接依赖的范围一致。
2、当第二直接依赖的范围是test的时候,依赖不会得以传递。
3、当第二依赖的范围是provided的时候,只传递第一直接依赖范围也为provided的依赖,且传递性依赖的范围同样为 provided;
4、当第二直接依赖的范围是runtime的时候,传递性依赖的范围与第一直接依赖的范围一致,但compile例外,此时传递的依赖范围为runtime;

我们这里举个例子来看:

①、第二依赖范围是 test

Maven_first pom.xml 文件如下:

然后Maven_second依赖Maven_fisrt,Maven_third依赖Maven-second,其pom.xml 文件如下:

Maven_second的 pom.xml

Maven_third的 pom.xml

我们发现在 Maven_third和 Maven_second 都没有 Maven_first 引入的 Junit 包,正好符合上面总结的第二点:当第二直接依赖的范围是test的时候,依赖不会得以传递。

②、第二依赖范围是 compile

如果我们将 Maven_first 的Junit 改为 compile,那么将会符合上面总结的第一点:当第二依赖的范围是compile的时候,传递性依赖的范围与第一直接依赖的范围一致。

6、依赖的排除

如果我们在当前工程中引入了一个依赖是 A,而 A 又依赖了 B,那么 Maven 会自动将 A 依赖的 B 引入当前工程,但是个别情况下 B 有可能是一个不稳定版,或对当前工程有不良影响。这时我们可以在引入 A 的时候将 B 排除。

比如:我们在Maven_first 中添加 spring-core,maven 会自动将 commons-logging添加进来,那么由于Maven_second 是依赖 Maven_first 的,那么 Maven_second 中将存在 spring-core(自带了commons-logging),这时候我们不想要 commons-logging,那该怎么办呢?我们上面第二大点提到了:

exclusions:用来排除传递性依赖

Maven_first 的 pom.xml 文件

由于 Maven_second 依赖 Maven_second,故Maven_second 存在 spring-core

如何排除呢?我们在 Maven_second 的 pom.xml 文件中添加如下代码:

再次查看工程:Maven_secondcommons-logging 已经移除了  

7、依赖的冲突

在maven中存在两种冲突方式:一种是跨pom文件的冲突,一致是同一个pom文件中的冲突。

①、跨 pom 文件,路径最短者优先。比如我们在 Maven_first 中的 Junit 是4.9版本的,Maven_second 中的 Junit 是4.8版本的,那么Maven_third 中的 Junit 将会是那个版本呢?

由上图我们可以看出,由于 Maven_second 是 Maven_third 的直接依赖,明显相比于 Maven_first 路径要短,所以 Maven_third 的 Junit 版本与 Maven_second 保持一致。

②、同一个pom.xml 文件,先申明者优先。

看 Maven_second

8、可选依赖

Optional标签标示该依赖是否可选,默认是false。可以理解为,如果为true,则表示该依赖不会传递下去,如果为false,则会传递下去。

我们是在 Maven_second 的 pom 文件中设定 Junit 不可传递,那么Maven_third 工程中将不会有来自 Maven_second 的 Junit 的传递。

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • 微服务中使用Maven BOM来管理你的版本依赖详解

    BOM简介 BOM(Bill of Materials)是由Maven提供的功能,它通过定义一整套相互兼容的jar包版本集合,使用时只需要依赖该BOM文件,即可放心的使用需要的依赖jar包,且无需再指定版本号.BOM的维护方负责版本升级,并保证BOM中定义的jar包版本之间的兼容性. 为什么要使用BOM 使用BOM除了可以方便使用者在声明依赖的客户端时不需要指定版本号外,最主要的原因是可以解决依赖冲突,如考虑以下的依赖场景: 项目A依赖项目B 2.1和项目C 1.2版本: 项目B 2.1依赖项目

  • 深入理解Maven的坐标与依赖

    在前边两节中,我们学习了Maven的基本概念以及何为Maven仓库,并且如何配置settings.xml文件等相关知识点.Maven的主要作用是可以帮助我们自动下载在pom.xml中配置添加的依赖.那么在本节中,我们将学习如何引入依赖. 知识点包括: Maven的坐标,Maven的依赖配置,依赖范围,传递性依赖,依赖调解,可选依赖,排除依赖,归类依赖和优化依赖 Maven的坐标 Maven的仓库中拥有着无数的构件,每一个构件都是一个jar或者war等文件,如果没有坐标,那么我们将无法唯一标识该构

  • Java如何通过Maven管理项目依赖

    项目的依赖 Java最大的一个优势之一应该是整个生态中无数的框架和API,我们创建实际的项目不可避免的都需要用到这些框架和API,而它们通常都是以JAR包的形式提供.我们之前在编译项目的时候,需要在classpath上存放依赖的JAR包.而且这些外部的JAR包还会有其他依赖.我们需要递归地一个个去下载所有这些外部依赖,并且要确保下载的版本都是正确的,当项目越来越复杂的时候,这是极其麻烦的事情,比如碰到JAR Hell的问题. Maven现在来拯救我们了,Maven可以自动帮我们做依赖管理,我们需

  • maven多模块项目依赖管理与依赖继承详解

    目录 maven多模块项目依赖管理与依赖继承 1.指定父模块与默认继承 2.依赖管理 关于maven项目依赖继承问题 只需要在父项目中加入 并且把父项目已POM的形式 然后在子项目中以<parent>标签 maven多模块项目依赖管理与依赖继承 1.指定父模块与默认继承 dependencies即使在子项目中不写该依赖项,那么子项目仍然会从父项目中继承该依赖项(全部继承) 父模块的pom <?xml version="1.0" encoding="UTF-8

  • 一篇文章带你了解Maven的坐标概念以及依赖管理

    目录 1.什么是坐标? ①.数学中的坐标 ②.Maven 中的坐标 ③.Maven 坐标和仓库,jar 包的关系 2.什么是依赖? 3.依赖的详细配置 4.依赖的范围 scope 1.compile 范围依赖 2.test 范围依赖 3.provided 范围依赖 4.runtime 范围依赖: 5.依赖的传递 我们这里举个例子来看: ①.第二依赖范围是 test ②.第二依赖范围是 compile 6.依赖的排除 7.依赖的冲突 8.可选依赖 总结 1.什么是坐标? ①.数学中的坐标 在平面上

  • 一篇文章带你了解Maven的继承和聚合

    目录 1.继承 2.聚合 总结 1.继承 需求场景: 有三个 Maven 工程,每个工程都依赖某个 jar 包,比如 Junit,由于 test 范围的依赖不能传递,它必然会分散在每个工程中,而且每个工程的jar 包版本可能不一致.那么如何管理各个工程中对于某个 jar 包的版本呢? 解决办法: 将那个 jar 包版本统一提取到 “父" 工程中,在子工程中声明依赖时不指定版本,以父工程中统一设定的为准,同时也便于修改. 操作步骤: ①.创建父工程 ②.在子工程中声明对父工程的引用 <!--

  • 一篇文章带你了解Maven的生命周期

    目录 1.什么是 生命周期? 2.Clean Lifecycle:在进行真正的构建之前进行一些清理工作 3.Default Lifecycle:构建的核心部分,编译.测试.打包.安装.部署等等 4.Site Lifecycle:生成项目报告,站点,发布站点. 总结 1.什么是 生命周期? Maven 强大的原因是有一个十分完善的生命周期,生命周期可以理解为项目构建步骤的集合,它定义了各个构建环节的执行顺序,有了这个顺序,Maven 就可以自动化的执行构建命令. Maven的核心程序中定义了抽象的

  • 一篇文章带你了解Java容器,面板及四大布局管理器应用

    目录 什么是容器? 什么是面板? JPanel面板 JScrollPane面板 什么是布局管理器? 绝对布局管理器 流布局管理器 边界布局管理 网格布局管理器 容器.面板.布局管理器之间的关系 总结 什么是容器? 在Java的GUI界面设计中,关于容器的理解,从字面意思我们就可以认为它是存放控件的地方,而这个地方依托在窗体之上,常用的容器是container. 而关于container容器我们应该有这样的认识:Swing组件中的窗体通常是与容器相关联的,所以在一般情况下,建立完JFrame窗体后

  • 一篇文章带你解决 IDEA 每次新建项目 maven home directory 总是改变的问题

    Maven是基bai于项目对象模型,可以通du过一小段描述信息来管理zhi项目的构建,报告和文档的软件项dao目管理工具. 重装个系统,各种问题,idea 也出现各种问题 装了个新版的 idea 2020 2.x 版本的,不知道咋回事,其他都好使,就是创建 SpringBoot 项目时: 加载 pom.xml 总是出错,原因就是,新建立的项目 maven home directory 总是乱,没有安装 设置的默认方式 我试了,改当前项目的,不好使 该默认设置,不好使,网上的其他方法也试了,很奇怪

  • 一篇文章带你了解Java Spring基础与IOC

    目录 About Spring About IOC Hello Spring Hello.java Beans.xml Test.java IOC创建对象的几种方式 Spring import settings Dependency Injection 1.构造器注入 2.set注入 3.拓展注入 P-namespcae&C-namespace Bean scopes singleton prototype Bean的自动装配 byName autowire byType autowire 小结

  • 一篇文章带你使用Typescript封装一个Vue组件(简单易懂)

    一.搭建项目以及初始化配置 vue create ts_vue_btn 这里使用了vue CLI3自定义选择的服务,我选择了ts.stylus等工具.然后创建完项目之后,进入项目.使用快捷命令code .进入Vs code编辑器(如果没有code .,需要将编辑器的bin文件目录地址放到环境变量的path中).然后,我进入编辑器之后,进入设置工作区,随便设置一个参数,这里比如推荐设置字号,点下.这里是为了生成.vscode文件夹,里面有个json文件. 我们在开发项目的时候,项目文件夹内的文件很

  • 一篇文章带你搞定SpringBoot中的热部署devtools方法

    一.前期配置 创建项目时,需要加入 DevTools 依赖 二.测试使用 (1)建立 HelloController @RestController public class HelloController { @GetMapping("/hello") public String hello(){ return "hello devtools"; } } 对其进行修改:然后不用重新运行,重新构建即可:只加载变化的类 三.热部署的原理 Spring Boot 中热部

  • 一篇文章带你搞定SpringBoot不重启项目实现修改静态资源

    一.通过配置文件控制静态资源的热部署 在配置文件 application.properties 中添加: #表示从这个默认不触发重启的目录中除去static目录 spring.devtools.restart.exclude=classpath:/static/** 或者使用: #表示将static目录加入到修改资源会重启的目录中来 spring.devtools.restart.additional-paths=src/main/resource/static 此时对static 目录下的静态

  • 一篇文章带你使用SpringBoot基于WebSocket的在线群聊实现

    一.添加依赖 加入前端需要用到的依赖: <dependency> <groupId>org.webjars</groupId> <artifactId>sockjs-client</artifactId> <version>1.1.2</version> </dependency> <dependency> <groupId>org.webjars</groupId> <

随机推荐