Spring Boot 应用程序中的 javax.servlet

Posted

技术标签:

【中文标题】Spring Boot 应用程序中的 javax.servlet【英文标题】:javax.servlet in Springboot Application 【发布时间】:2017-12-30 18:46:45 【问题描述】:

我有一个 SpringBoot 应用程序。一个类需要导入 javax.servlet.filter 并实现自定义的过滤器。它在本地构建成功,但在云服务器上启动失败并抛出 llegalStateExceptions。这是导致问题的过滤器类。删除过滤器后,应用程序在本地和云上成功运行。

我认为应用程序可能无法在 maven 中找到 javax.servlet api,或者是 servlet/embedded tomcat 不兼容问题。我们拥有来自 org.springframework.boot 的大部分依赖项。我们唯一与tomcat相关的部分是:

<dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-jdbc</artifactId>
    <version>LATEST</version>
</dependency>

我们没有以下内容:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <scope>provided</scope>
</dependency>

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

我尝试添加它们(单独和两者)并更改范围以编译或删除范围。各种依赖项都有细微的变化,但到目前为止没有任何效果。如果您有任何好的建议,请告诉我。

【问题讨论】:

【参考方案1】:

provided 范围意味着您希望该库由您部署代码的环境提供。你为什么要做这样的事?好吧,默认情况下,tomcat 会将包含 javax.servlet 类的库放在类路径中,许多其他服务器也这样做。这是一种允许容器提供者(tomcat、jboss、websphere 等)提供特定于其容器的库的自定义实现的方法。

Maven 将provided 范围解释为您不希望将库包含在任何捆绑包或部署、uberjar、zip 或其他任何东西中。 Spring-boot 生成一个 uber-jar - 也就是说,它将所有应用程序依赖项打包在应用程序的单个工件中(而不是将它们保存在单独的文件中,这是我们在古代使用 java 的方式,在我们知道更好之前) .

因此,如果您发现在运行时缺少该包,可能是因为它实际上不是您的容器中的provided,您必须自己通过完全删除范围标记来提供它。这将告诉 maven 将其捆绑在您的 uber-jar 中以在运行时使用。

查看您的具体问题,这些库都不应该是provided,因此您应该从所有依赖项中完全删除范围标签。如果这不起作用,您还有其他问题。

顺便说一句:顺便说一句,使用LATEST 作为任何依赖项的版本号是一个非常糟糕的主意。它违反了数十种最佳实践,并且针对某些二进制存储(例如,nexus)几乎无法正常工作并且无法保证。相反,您应该找出您打算使用的 tomcat-jdbc 版本,并改用绝对版本。在这种情况下,LATEST 版本几乎肯定是错误的版本。

【讨论】:

【参考方案2】:

我在SpringBoot应用程序中使用Gradle遇到过这样的问题,最后我发现问题是javax.servlet-api丢失了,根本原因是它的范围不正确,当它的范围是provided时,IDEA赢了'构建不完整,因此 servlet-api Jar 文件不包含在构建文件中。将范围从provided 更改为runtime 后,它已修复。可以参考这篇博客http://blog.csdn.net/u013360850/article/details/71520210

【讨论】:

【参考方案3】:

spring-boot 的问题在于,由于uber jar 很多,有时会多次提供 jar,因此要解决问题,因为已经嵌入了 Tomcat,我们可以简单地添加:

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

而不是像你尝试的那样。

【讨论】:

【参考方案4】:

如果您在 Gradle 构建中提供了运行时,只需运行项目(如果您使用的是 gradle)它可能会自动解决您的问题。在我的情况下也做了同样的事情

【讨论】:

以上是关于Spring Boot 应用程序中的 javax.servlet的主要内容,如果未能解决你的问题,请参考以下文章

如何处理 Spring Boot Rest 和 Jackson Deserializer 的 Javax 验证中的无效数字

Spring-Boot 如何正确注入 javax.validation.Validator

没有可用的“javax.sql.DataSource”类型的合格bean - spring-boot-batch

在运行 Spring MVC 应用程序时在 Spring Boot 中获取 NoSuchMethodError: javax.servlet.ServletContext.addServlet

Spring Boot(15)——自动配置Validation

在 tomcat 容器中具有多个 Web 应用程序的 Spring Boot 执行器引发 javax.management.InstanceAlreadyExistsException 异常