背景
新来同事搭建了一个springBoot项目,启动失败,如下提示Web application could not be started as there was no org.springframework.boot.web.servlet.server.ServletWebServerFactory bean defined in the context.
我比较纳闷,按说
spring-boot-starter-web
模块自带tomcat web容器啊,于是我就去看maven:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- undertow-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
<scope>provided</scope>
</dependency>
果不其然,同事在web模块排除了tomcat依赖,同时添加了undertow,但是scope指定的是provided级别,我记得provided在编译、测试时有效,但是在运行时无效,所以果断修改为compile,项目能够成功启动。
总结原因,还是对maven的scope知识点没有掌握牢固,今天我们简单总结一下。
scope取值与解释
Maven中使用 scope 来指定当前包的依赖范围和依赖的传递性。常见的可选值有:compile, provided, runtime, test, system 等。scope 主要是用在 pom.xml 文件中的依赖定义部分。
1. compile (默认)
描述 :compile 是 Maven 中的默认作用域,不指定 scope 的依赖会自动使用 compile 作用域。 使用阶段 :编译、测试、运行、打包。 特点 :在项目的所有阶段都可用。通常用于项目在运行时和编译时都需要的依赖。 典型场景 :项目的核心依赖,比如 Spring Framework、Hibernate 等通常会设为 compile。 示例:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${spring-boot.version}</version>
<!-- scope 默认为 compile -->
</dependency>
2. provided
描述 :provided 表示依赖在编译和测试阶段可用,但在运行时不会打包进最终的构件(如 JAR 或 WAR)。 使用阶段 :编译、测试。 特点 :运行时需要在外部提供这些依赖,比如应用服务器或运行环境会提供它们。 典型场景 :Servlet API、JSP API 等应用服务器或容器内置的库。 示例:
xml
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
3. runtime
描述 :runtime 作用域的依赖仅在运行和测试阶段可用,编译时不可用。 使用阶段 :运行、测试。 特点 :通常用于运行时才需要的库,编译时不需要。 典型场景 :数据库驱动。应用在编译时不需要数据库驱动,但运行时需要。 示例:
xml
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
<scope>runtime</scope>
</dependency>
4. test
描述 :test 作用域的依赖仅在测试阶段可用,编译、运行时不可用。 使用阶段 :测试。 特点 :用于编写和运行测试时需要的库。 典型场景 :JUnit、spring-boot-starter-test。 示例:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring-boot.version}</version>
<scope>test</scope>
</dependency>
5. system
描述 :system 作用域的依赖明确指定依赖文件的路径。它不会从 Maven 仓库中下载,而是直接使用本地系统的文件。作用域功能上类似于provided。 使用阶段 :编译、测试。 特点 :对文件路径有硬编码,无法与其他机器共享路径信息,不推荐使用。 典型场景 :通常不建议使用,可能用于一些本地库或特殊环境下的文件。 示例:
xml
<dependency>
<groupId>com.xiaoyu</groupId>
<artifactId>freedom</artifactId>
<version>1.0.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/libs/freedom.jar</systemPath>
</dependency>
6. import(仅适用于 )
描述 :import 作用域主要用于导入依赖的 BOM(Bill of Materials)文件,它通常在 中使用,用于控制和管理子项目的版本一致性。 使用阶段 :不直接用于编译或运行,而是用来将依赖版本管理导入到主项目。 典型场景 :用于多模块项目或需要版本统一的第三方依赖管理,如 Spring Boot 的 BOM。 示例:
xml
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
依赖传递
当项目 A 依赖项目 B,而项目 B 又依赖项目 C 时,Maven 会自动将项目 C 也作为项目 A 的依赖引入。这种自动处理依赖关系的特性称为传递性依赖。
传递规则取决于 Scope:
当前依赖Scope \ 传递依赖Scope | compile | provided | runtime | test | |
---|---|---|---|---|---|
compile | compile | - | runtime | - | |
provided | provided | provided | provided | - | |
runtime | runtime | - | runtime | - | |
test | - | - | - | - | weix |