从01开始 从01开始
首页
  • 计算机科学导论
  • 数字电路
  • 计算机组成原理

    • 计算机组成原理-北大网课
  • 操作系统
  • Linux
  • Docker
  • 计算机网络
  • 计算机常识
  • Git
  • JavaSE
  • Java高级
  • JavaEE

    • Ant
    • Maven
    • Log4j
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • Servlet
  • Spring
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC
  • SpringBoot
  • 学习网课的心得
  • 输入法
  • 节假日TodoList
  • 其他
  • 关于本站
  • 网站日记
  • 友人帐
  • 如何搭建一个博客
GitHub (opens new window)

peterjxl

人生如逆旅,我亦是行人
首页
  • 计算机科学导论
  • 数字电路
  • 计算机组成原理

    • 计算机组成原理-北大网课
  • 操作系统
  • Linux
  • Docker
  • 计算机网络
  • 计算机常识
  • Git
  • JavaSE
  • Java高级
  • JavaEE

    • Ant
    • Maven
    • Log4j
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • Servlet
  • Spring
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC
  • SpringBoot
  • 学习网课的心得
  • 输入法
  • 节假日TodoList
  • 其他
  • 关于本站
  • 网站日记
  • 友人帐
  • 如何搭建一个博客
GitHub (opens new window)
  • JavaSE

  • JavaSenior

  • JavaEE

    • JavaEE概念

    • Ant

    • Maven

      • 什么是Maven
      • 安装Maven
      • 第一个Maven项目
      • Maven的组成和配置
      • 快速创建Maven项目
      • 创建Web项目
      • Maven的生命周期和构建
      • Maven的依赖管理
        • 配置properties
        • 项目本身的坐标
        • 坐标的来源方式
        • 依赖范围 scope
        • 依赖冲突的问题
        • 锁定依赖版本
        • 查找依赖
        • 小结
      • Maven的插件管理
      • IDEA关于Maven的设置
      • 使用Maven完成dao层
      • 使用Maven完成service层
      • 使用Maven完成web层
      • Maven的拆分和聚合
      • Nexus的搭建
      • Nexus的使用
      • 安装第三方jar包到私服
      • Maven系列完结
      • Maven
    • 日志

    • Junit

    • JDBC

    • XML和JSON

    • Java
  • JavaWeb

  • Spring

  • 主流框架

  • SpringMVC

  • SpringBoot

  • Java并发

  • Java源码

  • JVM

  • 韩顺平

  • Java
  • Java
  • JavaEE
  • Maven
2023-05-15
目录

Maven的依赖管理

# 45.Maven的依赖管理

本文介绍关于依赖管理的更多概念   ‍

‍

# 配置properties

当我们需要用到的依赖多之后,一般会使用一个统一的版本,此时我们可以的配置可能是这样的:

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-web</artifactId>
	<version>5.0.2.RELEASE</version>
</dependency>

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-webmvc</artifactId>
	<version>5.0.2.RELEASE</version>
</dependency>

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-tx</artifactId>
	<version>5.0.2.RELEASE</version>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

‍

例如本例是使用5.0.2.RELEASE。此时我们可能遇到这样的问题:升级版本。那么我们需要将所有涉及到的版本都改一遍!而我们可以通过配置properties的方式来简化配置:

<properties>
	<spring.version>5.0.2.RELEASE</spring.version>
</properties>
1
2
3

‍

然后在用到的地方使用该properties:这样就可以统一修改版本号了,其实这是EL表达式的一种。

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-web</artifactId>
	<version>${spring.version}</version>
</dependency>
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-webmvc</artifactId>
	<version>${spring.version}</version>
</dependency>
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-tx</artifactId>
	<version>${spring.version}</version>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

‍

Maven自己会有一些内置属性:

  • ​${basedir}​ 项目根目录
  • ​${project.build.directory}​ 构建目录,缺省为target
  • ​${project.build.outputDirectory}​ 构建过程输出目录,缺省为target/classes
  • ​${project.build.finalName}​ 产出物名称,缺省为${project.artifactId}-${project.version}​
  • ​${project.packaging}​ 打包类型,缺省为jar
  • ​${project.xxx}​ 当前pom文件的任意节点的内容

‍

# 项目本身的坐标

每个 Maven 项目,都需要定义自己本身的坐标,例如本项目在pom.xml文件有这样的定义:

<!--项目名称,定义为组织名+项目名,类似包名-->
<groupId>com.peterjxl.LearnJavaMaven</groupId>

<!-- 模块名称 -->
<artifactId>hello-world</artifactId>

<!-- 当前项目版本号,snapshot 为快照版本即非正式版本,release 为正式发布版本 -->
<version>0.0.1-SNAPSHOT</version>
1
2
3
4
5
6
7
8

‍

‍

为什么项目也要定义坐标呢?因为项目本身也可以作为一个依赖,供其他项目使用!有很多开源项目,例如Log4j框架 (opens new window),其本身也是用Maven来管理的,也有引入其他依赖。

Maven对依赖的分类:

  • 直接依赖:项目中直接导入的jar包,就是该项目的直接依赖包。
  • 传递依赖:项目中没有直接导入的jar包,也就是项目直接依赖的jar包所需要的依赖,这些依赖也是项目所需要的。

‍

‍

# 坐标的来源方式

添加依赖需要指定依赖 jar 包的坐标,但是很多情况我们是不知道 jar 包的的坐标,可以通过如下网址查询:

  • http://search.maven.org (opens new window)
  • http://mvnrepository.com (opens new window)
  • 还有很多网站提供类似的服务,不一一介绍了

‍

网站搜索示例:搜索Spring

​

‍

然后就可以选择复制Maven的坐标,或者下载 JAR文件

​​

‍

‍

‍

# 依赖范围 scope

A 依赖 B,需要在 A 的 pom.xml 文件中添加 B 的坐标,

‍

添加坐标时需要指定依赖范围<scope>​,依赖范围包括:

  • compile:默认值,在编译、测试、打包和程序运行的时候需要用到的依赖
  • provided:只有在当 JDK 或者一个容器已提供该依赖之后才使用, provided 依赖在编译和测试时需要,在运行时不需要,比如:servlet 所用到的依赖,仅仅在编译时用到,在运行时,由于Tomcat已经有这些依赖了,因此在运行时不需要用到。
  • runtime:在运行和测试时需要,但在编译的时候不需要。比如 jdbc 的驱动包。由于运行时需要,所以runtime 范围的依赖会被打包。
  • test:test 范围依赖 在编译和运行时都不需要,它们只有在测试编译和测试运行阶段可用, 比如:junit。由于运行时不需要所以test 范围依赖不会被打包。
  • system:system 范围依赖与 provided 类似,但是你必须显式的提供一个对于本地系统中JAR文件的路径,需要指定 systemPath 磁盘路径,system 依赖不推荐使用。

‍

我们可以列个表格:

依赖范围 对于编译classpath有效 对于测试classpath有效 对于运行时classpath有效 例子
compile Y Y Y Spring-Core
test - Y - Junit
provided Y Y - Servlet-api
Runtime - Y Y JDBC驱动

‍

# 依赖冲突的问题

有时候,一个开源项目A,会依赖于另一个开源项目B;

而我们引入开源项目A的时候,Maven会将项目A,需要的依赖,也引入进来。例如,当我们引入Spring框架的时候:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.0.2.RELEASE</version>
</dependency>
1
2
3
4
5

‍

可以看到Spring还依赖于不少依赖:

​

‍

这样做有好处也有坏处:

  • 好处:引入一个依赖,就可以引入所有用到的依赖,不用一个一个的去引入
  • 坏处:当一个依赖A,需要用到依赖C;而另一个依赖B,也用到依赖C,并且需要的依赖C的版本还不同的时候...

‍

我们可以演示下,添加一个新的依赖spring-beans<:

 <dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>4.2.4.RELEASE</version>
    </dependency>
</dependencies>
1
2
3
4
5
6
7
8
9
10
11
12
13

虽然spring-context已经包含了spring-beans<,但我们现在是为了演示问题,所以特地添加的。

‍

‍

‍

我们可以通过IDEA来查看项目的依赖情况:首先打开Maven的工具面板,然后点击右上角的查看依赖关系(或者快捷键Ctrl + Shift + Alt + U)

​​​​

‍

我们可以看到,我们的项目的依赖情况,这里以一个网上的截图为例:

​​

‍

由下往上看,我们的项目,使用了两个依赖:

  • spring-beans,其用到了一个依赖spring-core
  • spring-context,其最后也是用到了spring-core
  • 两者的版本是不一样的,最后到底用哪个呢?

​

我们可以看看IDEA的视图,可以看到最后用的还是spring-core 5.0.2的版本:

​​​​​

‍

但如果说我们将依赖的顺序调换下:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-beans</artifactId>
    <version>4.2.4.RELEASE</version>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.0.2.RELEASE</version>
</dependency>
1
2
3
4
5
6
7
8
9
10
11

​​

‍

此时,用的就是4.2.4的版本了!

​​

​

因此我们引入依赖的时候,必须考虑如何解决。解决jar包冲突的方式:

  • 方式一:第一声明优先原则。哪个jar包的坐标在靠上的位置,这个jar包就是先声明的。先声明的jar包坐标下的依赖包,可以优先进入项目中。

  • 方式二:路径近者优先原则。直接依赖路径比传递依赖路径近,那么最终项目进入的jar包会是路径近的直接依赖包

  • 方式三【推荐使用】:直接排除法。当我们要排除某个jar包下依赖包,配置exclusions标签。内部可以不写版本号,因为此时依赖包使用的版本和默认和本jar包一样,例如本例中就是spring-beans的版本4.2.4。

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>4.2.4.RELEASE</version>
        <exclusions>
            <exclusion>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

‍

‍

‍

# 锁定依赖版本

maven工程是可以分父子依赖关系的。

凡是依赖别的项目后,拿到的别的项目的依赖包,都属于传递依赖。比如:当前A项目,被B项目依赖。那么我们A项目中所有jar包都会传递到B项目中。

B项目开发者,如果再在B项目中导入一套ssm框架的jar包,对于B项目是直接依赖,那么直接依赖的jar包就会把我们A项目传递过去的jar包覆盖掉。

为了防止以上情况的出现。我们可以把A项目中主要jar包的坐标锁住,那么其他依赖该项目的项目中,即便是有同名jar包直接依赖,也无法覆盖。

配置方法:使用<dependencyManagement>​标签

<dependencyManagement>
  <dependencies>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${spring.version}</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>${spring.version}</version>
    </dependency>

    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>${mybatis.version}</version>
    </dependency>

  </dependencies>
</dependencyManagement>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

‍

注意,锁定的jar包仅仅是锁定作用,并没有引入依赖。

‍

‍

# 查找依赖

有时候我们知道类名,但是不知道对应的Maven依赖,也可以通过搜索来找到。

打开 https://search.maven.org/

一. 已知全类名:输入fc:org.apache.poi.xssf.usermodel.XSSFWorkbook (注:fc 代表 full class)

二. 已知类名:输入c:类名(注:c 代表 class)

三. 已知 Group ID 或者 Artifact ID,g:com.alibaba a:druid

‍

# 小结

我们讲了什么是依赖,并且介绍了scope和依赖冲突的方式,下一篇我们来讲讲插件管理。

在GitHub上编辑此页 (opens new window)
上次更新: 2023/5/15 16:02:46
Maven的生命周期和构建
Maven的插件管理

← Maven的生命周期和构建 Maven的插件管理→

Theme by Vdoing | Copyright © 2022-2023 粤ICP备2022067627号-1 粤公网安备 44011302003646号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式