java - Springboot 为什么按照提供的方式设置 spring-boot-starter-tomcat
问题描述
将 Springboot maven 项目(版本 2.3.4.RELEASE)部署到外部 Tomcat 容器时,官方指南说您需要将“spring-boot-starter-tomcat”依赖项标记为已提供,但实际上即使不这样做,包含诸如“spring-boot-starter-tomcat”,“tomcat-embed-core”和“tomcat-embed-websocket”之类的lib的最终war包在tomcat8.5.54或tomcat 9.0中也可以正常工作,所以我对此感到困惑, “我们真的需要设置 spring-boot-starter-tomcat 吗?” ,任何人都可以解释为什么? “传统部署”
解决方案
您不希望在类路径上有多个版本的相同类。这可能会在运行时导致许多错误。例如,如果您有一个
public class MyServlet implements javax.servlet.Servlet
MyServlet.class
并且您将and javax.servlet-api.jar
(其中包含)打包javax.servlet.Servlet
到您的应用程序中,您可能会收到错误消息:
Servlet class MyServlet is not a javax.servlet.Servlet
发生的情况是:当应用程序类加载器加载时MyServlet
,它javax.servlet.Servlet
首先在应用程序中查找,然后在javax.servlet-api.jar
. 服务器将这个类与服务器类加载器加载的类进行比较,并得出结论它们不同,因为来自不同 JAR 的类不相等。如果应用程序在交付时没有javax.servlet-api.jar
发生这种情况:类加载器在它自己的类路径中找不到javax.servlet.Servlet
,所以它在父类加载器中查找。
备注:此示例实际上无法在 Tomcat 上重现。可能由于许多错误打包的应用程序对类加载规则有一个例外:特殊类,例如那些以WebappClassLoader
服务器的类加载器开头javax.servlet
或org.apache.tomcat
总是从服务器的类加载器加载的类(参见这些例外列表的源代码)。
TL;DR:由于上述评论,留spring-boot-starter-tomcat
在compile
范围内可能不会造成任何伤害,但这是不值得冒险的风险。
推荐阅读
- r - R:For循环仅更新向量中的最后一个元素
- javascript - 如何通过 ajax 将 JavaScript 变量转换为 PHP
- javascript - 布尔检查在 NodeJS 中不起作用
- c++11 - 如何在另一个命名空间中使用一个命名空间的指针,并且两个命名空间都在另一个类中使用
- mule - 如何在 Mule4 中生成动态 XML 响应?
- swift - 通过触摸该单元格中的按钮来删除 UITableViewCell
- javascript - 如何将 series-label 默认设置为 false 并更改 highchart 中系列标签文本的颜色
- c# - 用户双击时自动解密加密的exe文件的C#代码
- java - 无法通过 JAVA -8、64 位及更高版本的 NSIS 安装程序检查 Win-10 中已安装的 Java 版本
- testing - 如何使用马拉松测试工具(MarathonITE)从命令行运行几个测试用例或测试套件?