Maven中optional和scope元素的使用弄明白了吗

在梳理项目的过程中发现很多开发同学对 Maven 依赖文件的配置并不了解,特别是对 Maven 的 optional 元素和 scope 元素的使用也非常随意。这就会导致发布的 jar 包或 war 包非常 “胖”、编译速度慢,而且还很容易生产 jar 冲突等问题。本篇文章从 optional 和 scope 的使用场景入手,让项目实现一波瘦身。

optional 元素

这里以 Spring Boot 项目中的使用为例,比如我们在项目中经常使用的热部署组件 spring-boot-devtools,就可以使用 optional 元素来进行定义,对应 pom 文件中配置如下:

<!--devtools 热部署-->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-devtools</artifactId>
  <optional>true</optional>
</dependency>

那么,这里的 optional 元素设置为 true 表示何意?optional 是 Maven 依赖 jar 时的一个选项,表示该依赖是可选的,项目之间依赖不传递。不设置 optional(默认)或者 optional 是 false,表示传递依赖。

文字描述可能比较抽象,下面用具体实例场景来进行更直观的描述,这里假设有两个项目 A 和 B,其中 A 为父项目,B 为子项目。在父项目中引入了单元测试的依赖:

<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.12</version>
</dependency>

下面针对 optional 元素的不同值进行讲解。

optional 元素默认值(false)

当父项目添加 junit 依赖时,并未添加 optional 选项,也就是默认的 optional 元素的值为 false。

此时,当子项目依赖父项目时,父项目 A 和子项目 B 的关系如下:

父项目并未设置 optional 元素为 true,那么便具有依赖传递性。此时,子项目 B 中会直接引入父项目 A 中引入的 Junit 的 jar 包。也就是说 B 项目打包时,jar/war 包中会包含 junit 的 jar 包。

optional 元素为 true

当父项目引入 junit 依赖时,设置 optional 元素为 true。那么,子项目 B 便有了更多的选择。

如果项目 B 不需要 Junit 的 jar 包,那么在其 pom 文件中不需进行任何处理便可以。如果 B 项目也需要对应的 jar 包依赖,可以有两种选择:第一、A 项目中对应依赖的 optional 设置为 false 或去掉;第二、B 项目中直接引入需要的该依赖。

parent 继承的情况

我们经常会在 parent 项目中配置统一的依赖版本控制,如下:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <optional>true</optional>
    </dependency>
  </dependencies>
</dependencyManagement>

此时,如果 B 项目需要 Junit 的 jar 包,可以直接在项目中引入,这里父项目中的 optional 配置对子项目并无影响。
综上所述,在 Maven 项目中,恰当的使用 optional 配置,可以在很大程度上减少 jar 包的大小,提升编译和发布速度。

scope 元素

上面讲完了 optional 元素的使用,再来看看 scope 的使用。
scope 元素主要用来控制依赖的使用范围,指定当前包的依赖范围和依赖的传递性,也就是哪些依赖在哪些 classpath 中可用。常见的可选值有:compile, provided, runtime, test, system 等。

compile(编译)

默认值。compile 表示对应依赖会参与当前项目的编译、测试、运行等,是一个比较强的依赖。打包时通常会包含该依赖,部署时会打包到 lib 目录下。比如:spring-core 这些核心的 jar 包。

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>

test(测试)

scope 为 test 表示依赖项目仅参与测试环节,在编译、运行、打包时不会使用。最常见的使用就是单元测试类了:

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

类似单元测试这样的依赖,如果不设置 scope 为 test,很显然它们会被打包、发布,但其实真是环境中并无什么作用。

runntime(运行时)

runntime 仅仅适用于运行和测试环节,在编译环境下不会被使用。比如编译时只需要 JDBC API 的 jar,而只有运行时才需要 JDBC 驱动实现。

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

provided(已提供)

provided 适合在编译和测试的环境,和 compile 功能相似,但 provide 仅在编译和测试阶段生效,provide 不会被打包,也不具有传递性。

比如:上面讲到的 spring-boot-devtools、servlet-api 等,前者是因为不需要在生产中热部署,后者是因为容器已经提供,不需要重复引入。

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

system

system 范围依赖与 provided 类似,不过依赖项不会从 maven 仓库获取,而需要从本地文件系统提供。使用时,一定要配合 systemPath 属性。不推荐使用,尽量从 Maven 库中引用依赖。

<dependency>
 <groupId>sun.jdk</groupId>
 <artifactId>tools</artifactId>
 <version>1.5.0</version>
 <scope>system</scope>
 <systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>

scope 依赖的传递性

上面讲解 scope 的不同参数值,针对这些参数值,在多个项目中的依赖传递性如下:

其中 B 依赖 A,C 依赖 B,传递性的关键是 B 依赖 A 时所设置的 scope 值,当 B 采用不同的值时对应的依赖关系如下:当 B 通过 test 或 provided 依赖 A 时,C 不依赖 A;当 B 通过 runtime 或 compile 依赖 A 时,C 依赖 A;

小结

经过上面对 Maven 的 optional 和 scope 元素的详细讲解,想必你已经可以对项目中的配置进行排查,确保精确的使用项目与项目之间的依赖,而不是每个项目都引入大而全的依赖文件,导致项目臃肿,编译缓慢,冲突不断。

到此这篇关于Maven中optional和scope元素的使用弄明白了吗的文章就介绍到这了,更多相关Maven optional scope 内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 详解Maven optional关键字透彻图解

    写在前面 本来想写一篇「如何自定义Spring Boot Starter」,但是为了更好理解 Starter 的一些设计理念和其中的关键点,所以提前将一些细节内容单独提取出来讲解说明 在 Maven pom.xml 中,你经常会看到依赖项中有类似下面的代码: <dependency> <groupId>sample.ProjectA</groupId> <artifactId>Project-A</artifactId> <version&

  • maven依赖关系中的<scope>provided</scope>使用详解

    关于maven依赖中的<scope>provided</scope>使用 scope的其他参数如下: compile 默认的scope,表示 dependency 都可以在生命周期中使用.而且,这些dependencies 会传递到依赖的项目中.适用于所有阶段,会随着项目一起发布 provided 跟compile相似,但是表明了dependency 由JDK或者容器提供,例如Servlet AP和一些Java EE APIs.这个scope 只能作用在编译和测试时,同时没有传递性

  • Maven中optional和scope元素的使用弄明白了吗

    在梳理项目的过程中发现很多开发同学对 Maven 依赖文件的配置并不了解,特别是对 Maven 的 optional 元素和 scope 元素的使用也非常随意.这就会导致发布的 jar 包或 war 包非常 "胖".编译速度慢,而且还很容易生产 jar 冲突等问题.本篇文章从 optional 和 scope 的使用场景入手,让项目实现一波瘦身. optional 元素 这里以 Spring Boot 项目中的使用为例,比如我们在项目中经常使用的热部署组件 spring-boot-de

  • 使用Maven中的scope总结

    目录 Maven中的scope总结 Maven中的scope主要有以下6种 Maven中<scope>参数</scope>配置 解决maven项目中无法打包生成空文件夹的问题 Maven中的scope总结 Maven中的scope主要有以下6种 接下来分别介绍下这几种scope: compile 不声明scope元素的情况下的默认值:compile表示被依赖包需要参与当前项目的编译,包括后续的测试,运行周期也参与其中,是一个比较强的依赖:打包的时候通常需要包含进去. provide

  • Maven中pom.xml配置文件详细介绍

    setting.xml主要用于配置maven的运行环境等一系列通用的属性,是全局级别的配置文件:而pom.xml主要描述了项目的maven坐标,依赖关系,开发者需要遵循的规则,缺陷管理系统,组织和licenses,以及其他所有的项目相关因素,是项目级别的配置文件. 基础配置 一个典型的pom.xml文件配置如下: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org

  • maven中pom.xml详细介绍

    POM 代表工程对象模型.它是使用 Maven 工作时的基本组建,是一个 xml 文件.它被放在工程根目录下,文件命名为 pom.xml. POM 包含了关于工程和各种配置细节的信息,Maven 使用这些信息构建工程. POM 也包含了目标和插件.当执行一个任务或者目标时,Maven 会查找当前目录下的 POM,从其中读取所需要的配置信息,然后执行目标.能够在 POM 中设置的一些配置如下: project dependencies plugins goals build profiles pr

  • PHP获取数组中重复最多的元素的实现方法

    本文实例讲述了PHP获取数组中重复最多的元素的实现方法.分享给大家供大家参考.具体方法如下: 复制代码 代码如下: <?php  /**   *    * Created on 2014-4-1   * @param   array $array   * @param   int [optional] $length   * @return  array   */  function mostRepeatedValues($array,$length=0){      if(emptyempty

  • 在maven中引入本地jar包的步骤

    目录 1 起因 2 解决方案 2.1 在pom中引入 2.2 Spring Boot 打包处理 2.3 拓展: Spring Boot 打包加入其它资源 1 起因 在和一些第三方厂商对接的过程中, 偶尔会遇到对方提供的SDK自带maven无法获取的jar包的情况(对于开源激进者的笔者很讨厌这种行为) 我们该如何处理这种情况呢, 其实解决思路很简单: 在pom中引入本地jar 打包时本地jar包含在内 让我们来看看具体怎么操作吧 idea中虽然可以在项目配置加入, 但打包时会报错, 相关的处理方案

  • 基于idea Maven中的redis配置使用详解

    pom.xml文件需要的内容 <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> &

  • Maven中Could not find artifact XXXX的错误解决

    我目前碰到的是: Could not find artifact com.alibaba.cloud:spring-cloud-alibaba-dependencies:pom:2.1.0 RELEASE in central 出现问题的原因其实很简单,写错了版本号!!2.1.0 RELEASE中间不该是空格而应该是.,即应该写成如下: <dependencyManagement>     <dependencies>       <!-- spring cloud alib

  • 详解如何在Angular中快速定位DOM元素

    在使用Angular2+中,经常会想快速的去选择DOM上的某个元素,如果是刚上手Angular,有可能直接就使用原生DOM操作或者导入jQuery再进行DOM操作,既然都使用了Angular了,有没有更好的方法呢?答案是肯定的. 通过ElementRef 先上代码: import {Component, ElementRef, OnInit} from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.

  • Java8中Optional类型和Kotlin中可空类型的使用对比

    本文主要给大家介绍了关于Java8中Optional类型和Kotlin中可空类型使用的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍: 在 Java 8中,我们可以使用 Optional 类型来表达可空的类型. package com.easy.kotlin; import java.util.Optional; import static java.lang.System.out; /** * Optional.ofNullable - 允许传递为 null 参数 *

随机推荐