前面讲了maven一些关于Maven的简单知识,今天我给大家分享一些Maven的依赖管理。我相信用过maven的人都知道,它很重要的功能就是通过依赖来添加jar包。

让我们领略一下Maven是怎么管理我们的jar包的。

一、Maven坐标

1.1、数学中的坐标

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

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

1.2、Maven 中的坐标

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

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

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

      <groupid>com.zyh.maven</groupid>

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

      <artifactid>Maven_ch01</artifactid>
    3)version:当前项目的版本
      <version>0.0.1-SNAPSHOT</version>
     

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

  仓库是Maven 用来存放 jar 包的地方。

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

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

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

      com\zyh\maven\Maven-ch01\1.0-SNAPSHOT  

      

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

      Maven-ch01-1.0-SNAPSHOT.jar

    也就是 artifactid-version.jar

二、依赖

什么是 依赖?相信有过一定开发经验的人知道,每当我们需要使用某个框架时,比如 SpringMVC,那么我们需要导入相应的 jar 包,但是手动导入包的时候,往往会漏掉几个 jar 包,

那么在使用该框架的时候系统就会报错。那么我们就说导入的包与未导入的包存在依赖关系。而使用 Maven,我们只需要在 pom.xml 文件中进行相应的配置,它就会帮助我们自动管理 jar 包之间的依赖关系。

2.1、依赖的详细配置

  为了避免不知道说的哪些配置属性,看下面图就明白了,就是dependency下的属性配置,全部有9个,讲其中的7个。

  

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

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

  1)groupId、artifactId、version是依赖的基本坐标,缺一不可,这三个可以不用将,都知道,重要的是除了这三个之外的配置属性需要我们理解

  2)type:依赖的类型,比如是jar包还是war包等

    默认为jar,表示依赖的jar包

    注意:<type>pom.lastUpdated</type> 这个我们在上面添加servlet-jar的时候就遇到过,看到lastUpdated的意思是表示使用更新描述信息,占位符作用,通俗点讲,选择该类型,

      jar包不会被加载进来,只是将该jar包的一些描述信息加载进来,使别的jar包在引用他时,能够看到一些相关的提示信息,仅此而已,所以说他是个占位符,只要记住他的jar包不会被加载进来。

  3)optional:标记依赖是否可选。默认值false

    比如struts2中内置了log4j这个记录日志的功能,就是将log4j内嵌入struts2的jar包中,而struts2有没有log4j这个东西都没关系,有它,提示的信息更多,没它,也能够运行,

    只是提示的信息就相对而言少一些,所以这个时候,就可以对它进行可选操作,想要它就要,不想要,就设置为false。

  4)exclusions:排除传递依赖,解决jar冲突问题

    依赖传递的意思就是,A项目 依赖 B项目,B项目 依赖 C项目,当使用A项目时,就会把B也给加载进来,这是传递依赖,依次类推,C也会因此给加载进来。

    这个有依赖传递有好处,也有坏处,坏处就是jar包的冲突问题,比如,A 依赖 B(B的版本为1),C 依赖 B(B的版本为2),如果一个项目同时需要A和C,那么A,C都会传递依赖将B给加载进来,

    问题就在这里,两个B的版本不一样,将两个都加载进去就会引起冲突,这时候就需要使用exclusions这个属性配置了。maven也会有一个机制避免两个都加载进去,

    maven 默认配置在前面的优先使用,但是我们还是需要使用exclusions来配置更合理,这里使用spring bean 和 struts2 spring plugin 来举例子说明这个问题并使用exclusions解决这个问题。

    (spring bean 和 struts2 spring plugin都需要依赖spring-core,但版本不一样)

    从本地仓库中找到这两个jar包

     

    maven自己的解决方案如下:

      maven 默认配置在前面的优先使用,下面是证明

      先将spring-beans加载进去的,所以会将spring-beans依赖的spring-core的版本加载进来。

      

    先将struts2-spring-plugin加载进来,那么就会将其依赖的spring-core的版本加载进来

      

    

    使用exclusions来配置

      即使struts2-spring-plugin 配置在前面,也需要使用3.2.0版本。则需要为struts2-spring-plugin 排除依赖(不使用3.0.5依赖)

      

    注意:这样,就将struts2-spring-plugin依赖的spring-core的版本排除依赖了,也就是该依赖的spring-core不会在加载进来,查看代码,看是否符合要求,如果不符合要求,需要手动的修改

    

2.2、依赖的范围scope

  scope:依赖范围,意思就是通过pom.xml加载进来的jar包,来什么范围内使用生效,范围包括编译时,运行时,测试时

  

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

1)compile 范围依赖
  对主程序是否有效:有效
  对测试程序是否有效:有效
  是否参与打包:参与
  是否参与部署:参与
  典型例子:log4j

  默认值,如果选择此值,表示编译、测试和运行都使用当前jar
2)test 范围依赖
  对主程序是否有效:无效
  对测试程序是否有效:有效
  是否参与打包:不参与
  是否参与部署:不参与
  典型例子:Junit

  表示只在测试时当前jar生效,在别的范围内就不能使用该jar包。例如:junit 。此处不写也不报错,因为默认是compile,compile包扩了测试
3)provided 范围依赖
  对主程序是否有效:有效
  对测试程序是否有效:有效
  是否参与打包:不参与
  是否参与部署:不参与
  典型例子:servlet-api.jar,一般在发布到 服务器中,比如 tomcat,服务器会自带 servlet-api.jar 包,所以provided 范围依赖只在编译测试有效。 

  表示编译和测试时使用当前jar,运行时不在使用该jar了。例如:servlet-api、jsp-api等。 

  分析:

  什么意思呢? 在我们以前创建web工程,编写servlet或者jsp时,就没导入过jar包把,因为myeclipse或者别的ide帮我们提供了这两个jar包,内置了,

  所以我们在编译期测试期使用servlet都不会报缺少jar包的错误,而在运行时期,离开了myeclipse或别的ide,就相当于缺失了这两个jar包,但此时tomcat又

  会帮我们提供这两个jar,以便我们不会报错,所以,这两个很特殊。看图

    1)开发阶段(MyEclipse提供),看下图以此证明我们说的

      java web 5.0项目: 

      java web 6.0项目:

    2)运行阶段(tomcat提供)   

       

    所以,根据这个特点,如果使用maven开发项目,就不是web项目了,那么myeclipse就不会在给我们提供这两个jar包,我们就必须自己手动通过坐标从仓库中获取,

    但是针对上面的分析,当运行的时候,tomcat会帮我们提供这两个jar包,所以我们自己从仓库中获取的jar包就不能和tomcat中的冲突,

    那么就正好可以通过provided这个属性,来设置这两个jar的作用范围,就是在变异时期和测试时期生效即可。这个例子就可以解释上面创建maven web时产生的错误和解决方案了。

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

  表示测试和运行时使用当前jar,编译时不用该jar包。例如:JDBC驱动。JDBC驱动,在编译时(也就是我们写代码的时候都是采用接口编程,压根就没使用到JDBC驱动包内任何东西,

    只有在运行时才用的到,所以这个是典型的使用runtime这个值的例子),此处不写也不报错,理由同上。

5)表示我们自己手动加入的jar包,不属于maven仓库(本地,第三方等),属于别得类库的这样的jar包,只在编译和测试期生效,运行时无效。一般不用

四、依赖传递

  比如我们创建三个Maven 工程,maven-first,maven-second以及maven-third,而third依赖于second,second又依赖于first,

  那么我们说 second 是 third 的第一直接依赖,first是second的第二直接依赖。而first是third的间接依赖。  

  

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

    

  总结如下:    

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

五、调节原则

  这个就是maven解决传递依赖时jar包冲突问题的方法,按照两种原则,上面已经介绍了一种了,就是下面的第二原则

  1)第一原则:路径近者优先原则

    A-->B-->C-->D-->X(1.6)

    E-->D-->X(2.0)

    使用X(2.0),因为其路径更近 

  2)第二原则:第一声明者优先原则。就是如果路径相同,maven 默认配置在前面的优先使用

    A-->B --> X(1.6)

    C-->D--> X(2.0)

    这样就是路径相同,那么如果A在前面,C在后面,则使用X(1.6)

    maven会先根据第一原则进行选择,第一原则不成,则按第二原则处理。

好就点“推荐”哦!

Maven(六)之依赖管理的更多相关文章

  1. 4.Maven概念模型,maven的生命周期,Maven坐标,依赖管理(依赖范围,依赖声明),仓库管理,私服概念

     1 maven概念模型 2 maven的生命周期,项目构建过程 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdG90b3R1enVvcXVhbg== ...

  2. Maven教程3(依赖管理)

    Maven教程2(Eclipse配置及maven项目) Maven项目,依赖,构建配置,以及构件:所有这些都是要建模和表述的对象.这些对 象通过一个名为项目对象模型(Project Object Mo ...

  3. Maven解读:项目依赖管理如何优化

    Github地址:https://github.com/zwjlpeng/Maven_Detail Maven最大的好处莫过于其强大的依赖管理系统,在Pom配置文件中指定项目需要的Jar包的坐标,Ma ...

  4. 从初识Maven到使用Maven进行依赖管理和项目构建

    前些天就安装了Maven,以备自己以后整合项目用,尤其是我们的ssh,ssm项目.想必好多人在开始的时候并不清楚Maven是什么,它能够帮助我们干什么. 所以在学习Maven之前我们一定要知道它是什么 ...

  5. Maven最佳实践:管理依赖

    From:http://juvenshun.iteye.com/blog/337405 Maven最佳实践:管理依赖 "If I have seen further it is by sta ...

  6. Maven01——简介、安装配置、入门程序、项目构建和依赖管理

    1 Maven的简介 1.1 什么是maven 是apache下的一个开源项目,是纯java开发,并且只是用来管理java项目的 Svn eclipse   maven量级 1.2 Maven好处 同 ...

  7. 【spring-boot 源码解析】spring-boot 依赖管理

    关键词:spring-boot 依赖管理.spring-boot-dependencies.spring-boot-parent 问题 maven 工程,依赖管理是非常基本又非常重要的功能,现在的工程 ...

  8. 廖雪峰Java12maven基础-1maven入门-2依赖管理

    maven 如果我们的项目依赖第三方的jar包: Commons Logging发布的jar包在那里下载? 使用Log4j需要哪些jar包 其他依赖:junit,Javamail,MySQL驱动... ...

  9. Gradle Maven 依赖管理

    仓库管理简介 本质上说,仓库是一种存放依赖的容器,每一个项目都具备一个或多个仓库. Gradle支持以下仓库格式: Ivy仓库 Maven仓库 Flat directory仓库 我们来看一下,对于每一 ...

随机推荐

  1. linux系统安装配置exim4(源码安装)

    一.Exim4概述 Exim是一个MTA(Mail Transfer Agent,邮件传输代理)服务器软件,该软件基于GPL协议开发,是一款开源软件.该软件主要运行于类UNIX系统.通常该软件会与Do ...

  2. 【浅谈web安全】大企业安全:从员工下手

    目前所有的企业都存在这方面的问题,比如员工把服务器和后台密码直接明文保存在云笔记和网盘中,员工企业邮箱密码跟外部个人密码一致等等,通常我们在入侵的时候只要在微博搜索一个目标公司的员工,拿到常用密码后登 ...

  3. MAC 上传文件到github

    在IOS中,经常需要上传文件到github.以桌面上的一个文件夹为例: 步骤1: cd 到该文件夹下,建立POD文件. $ cd /Users/andy/Desktop/openinstallSDK ...

  4. Jsp/html页面删除前进行删除提示

    HTML代码 <body> <a href="javascript:if(window.confirm('是否?')){window.location.href='test ...

  5. 通俗易懂的Java序列化原理

    序列化能干吗? (1)通过序列化可以把数据永久地保存到硬盘上(通常存放在文件里) (2)利用序列化实现远程通信,即在网络上传送对象的字节序列. 网上搜索的都是这样的解释,抽象,难懂. 我当时看见这两问 ...

  6. 为什么Java字符串是不可变对象?

    转自 http://developer.51cto.com/art/201503/468905.htm 本文主要来介绍一下Java中的不可变对象,以及Java中String类的不可变性,那么为什么Ja ...

  7. 原创: rsync软件服务利用ansible实现一键化部署

    ---恢复内容开始--- 首先创建一个脚本文件 /server/tools/peizhi.sh cat  /server/tools/peizhi.sh cat >>/etc/rsyncd ...

  8. java读取txt文件内容

    package read; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; public ...

  9. makefile初步制作,arm-linux- (gcc/ld/objcopy/objdump)详解

    在linux中输入vi Makefile 来实现创建Makefile文件 注意:命令行前必须加TAB键 例如:将两个文件led.c和crt0.S汇编文件,制作一个Makefile文件 led.bin ...

  10. 自己编写服务启动脚本(一):functions文件详细分析和说明

    本文目录: 1.几个显示函数2.action函数3.is_true和is_false函数4.confirm函数5.pid检测相关函数 5.1 checkpid.__pids_var_run和__pid ...