首页 > 解决方案 > 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 吗?” ,任何人都可以解释为什么? “传统部署”

标签: javaspring-boottomcat

解决方案


您不希望在类路径上有多个版本的相同类。这可能会在运行时导致许多错误。例如,如果您有一个

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.servletorg.apache.tomcat总是从服务器的类加载器加载的类(参见这些例外列表的源代码)。

TL;DR:由于上述评论,留spring-boot-starter-tomcatcompile范围内可能不会造成任何伤害,但这是不值得冒险的风险。


推荐阅读