场景描述:
idea 社区版IDE,应为生产环境要优化配置tomcat参数,要外置单独的tomcat部署。所以pom文件中排除掉spring boot tomcat后,再加入自带的tomcat,scope设置为provide仅在编译和测试时加入依赖,但在运行阶段由运行环境提供,运行阶段不用打包。当点击idea application的debug或run的时候就会启动不起来。
现象与问题:
曝出如下错误:
Caused by: java.lang.ClassNotFoundException: jakarta.servlet.ServletContext
原因:
依赖范围(Scope)配置问题
若 Servlet API 的依赖被标记为 provided,IDEA 社区版默认不会将其加入运行时的类路径,导致类找不到。专业版就不会有这个问题,花钱的就是不一样啊。
解决方法:
1.开发环境本地想启动起来的话,需要把provided 的依赖包配置进去。下图红色标记的前面打勾。
2.把provide改为compile(不建议,这样就用不到外置的tomcat了。与场景需求矛盾。)
依赖范围(Scope)配置问题:若 Servlet API 的依赖被标记为 provided,IDEA 社区版默认不会将其加入运行时的类路径,导致类找不到
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>compile</scope> <!-- 或删除 scope 标签 -->
</dependency>
这种问题可以问DS,尝试她列举的方法。解决这个问题需要对scope的参数适用范围特别熟悉。而且还要知道idea免费版和社区版有哪些区别。
附录:
maven scope 参数详解。
在 Maven 里,scope
是用来设定依赖项在项目不同阶段的使用范围与依赖传递性的。下面是 scope
各个参数的含义:
1. compile
(默认值)
compile
是依赖项的默认作用域。具备以下特点:
- 使用范围:依赖项在编译、测试、运行阶段均可用。
- 依赖传递性:具备传递性,即当 A 依赖 B,B 依赖 C 时,若 B 对 C 的依赖作用域是
compile
,那么 A 也会依赖 C。
示例:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<!-- scope 默认是 compile -->
</dependency>
2. provided
provided
意味着该依赖项在编译和测试阶段可用,但在运行阶段由运行环境提供。特点如下:
- 使用范围:编译和测试阶段可用,运行阶段不用。
- 依赖传递性:具备传递性。
示例:在 Java Web 项目里,Servlet API 一般由 Servlet 容器(像 Tomcat)提供,所以可将其依赖作用域设为 provided
。
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
3. runtime
runtime
表示依赖项在运行和测试阶段需要,但编译阶段无需。特点如下:
- 使用范围:测试和运行阶段可用,编译阶段不用。
- 依赖传递性:具备传递性。
示例:JDBC 驱动通常在运行时才需要,编译时无需。
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
<scope>runtime</scope>
</dependency>
4. test
test
表明依赖项仅在测试编译和测试运行阶段可用。特点如下:
- 使用范围:仅在测试阶段可用。
- 依赖传递性:不具备传递性。
示例:JUnit 是常用的测试框架,仅在测试时使用。
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
5. system
system
和 provided
类似,不过 system
依赖需要显式指定本地系统上的 JAR 文件路径。特点如下:
- 使用范围:编译和测试阶段可用,运行阶段不用。
- 依赖传递性:具备传递性。
示例:
<dependency>
<groupId>com.example</groupId>
<artifactId>custom-library</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${basedir}/lib/custom-library.jar</systemPath>
</dependency>
6. import
(仅适用于 <dependencyManagement>
中的 <dependency>
)
import
作用域只在 pom.xml
的 <dependencyManagement>
里使用,它允许导入另一个 POM 的 <dependencyManagement>
部分。特点如下:
- 使用范围:不直接影响依赖的使用范围,而是用于管理依赖版本。
- 依赖传递性:不具备传统意义的依赖传递性,仅用于版本管理。
示例:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.5.4</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
通过合理运用这些 scope
参数,能精确控制项目依赖项的使用范围与传递性,进而优化项目的构建和运行。