scopeprovided解析:探究依赖管理中scopeprovided的应用场景

发布时间:2023-05-18

一、scope provided 概述

在 Maven 的依赖管理范畴中,scope provided 代表依赖关系的一种“范畴”,与被依赖项目的编译构建不带来实际用处的依赖关系,通常以 optionalprovided 为属性。 换句话说,scope provided 设定的依赖关系只在编译期和测试期中生效,并在运行时被丢弃。这意味着,该依赖项只在项目的编译和测试中有效。

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

在上面的代码例子中,与 servlet-api 相关联的依赖项的作用仅限于编译和测试,在运行时不会被打包。如果用户所在的容器已经包含了 servlet-api 的库,就不必将它打包进 war 文件中,因此该依赖此时可用于编译,但不用于部署。

二、scope provided 的使用场景

1. 与 Java 标准库相关的依赖库

与应用程序运行环境相关的库,比如 Java 标准库,即使没有将其作为 Maven 依赖项导入,Java 运行时环境也将它们提供给应用程序。 例如,如果我们想要为 servlet 应用程序设置 ContextPath,则只需要导入 web.xml 文件就可以了,这样就可以通过 web 服务器运行和测试应用程序。在这种情况下,servlet-api 与 Java 标准库相关,因此我们可以将其声明为 provided,而不必将其打包到生产环境中:

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

2. 减少部署时的依赖项

当项目打算部署时,我们通常会将其从测试环境中移植到生产环境中。在此过程中,需要将我们已经编译过的代码移植到生产环境,并将所有依赖库(除 Java 标准库之外)放在一个 classpath 中。一般来说,同样的依赖包会被多个依赖库中所使用,无需重复下载或者打包到多个部署包中。因此为了提高效率,最好将所有这些依赖项打包在一个单独的文件中,让所有应用程序都可以共享它们而不用重复下载。 这就是 scope provided 的另一个用例:它能帮助我们仅将必须部署的依赖项打包到生产环境中,而不会重复打包在它们依赖的多个模块中。我们可以使用该范畴来告诉 Maven,一些依赖仅在 JAR 打包时有效,而不是在 WAR 或 EAR 打包时有效。

3. 与插件相关的范畴

Maven 插件是 Maven 生态系统中非常重要的一部分,Maven 插件通常也会有自己的宿主环境(如 Jetty 或 Tomcat)。在某些情况下,插件可能需要一些额外的依赖项来执行其任务。为了提供这些支持,将这些插件的依赖项声明为插件的 scope provided 是有意义的,因为它将允许这些依赖项在插件代码运行时被查找到,但不会被打包进用户项目中。

<plugins>
   <plugin>
          <groupId>org.eclipse.jetty</groupId>
          <artifactId>jetty-maven-plugin</artifactId>
          <version>9.4.31.v20200723</version>
      <dependencies>
          <dependency>
              <groupId>javax.servlet</groupId>
              <artifactId>javax.servlet-api</artifactId>
              <version>3.1.0</version>
              <scope>provided</scope>
          </dependency>
      </dependencies>
   </plugin>
</plugins>

三、范畴 unused 的缺陷

相对于范畴 provided 的优点,unused 的范畴不仅编译时用不到,并且 test 范畴通常代表着较大的测试代码,而且通常不需要在运行时打包。因此,它的适用范围通常更小。 然而,unused 范畴的一个缺陷是无法自动删除所有未使用的依赖项,一些用户仍然有一些未删除的垃圾文件,这会使项目变得丑陋,难以维护。

结论

范畴 provided 是作为 Maven 支持库中最常用的范畴之一。在依赖管理中,scope provided 常见的使用场景是:与 Java 标准库相关的依赖库、减少部署时的依赖项、与插件相关的范畴。unused 的范畴与之相比,它的使用范围通常更小,且不能自动删除未使用的依赖项,将文件留下来会使项目难以维护,变得丑陋。