39

当我尝试使用 Spring Boot 运行 Spring MVC 应用程序时,我遇到了异常...

ContainerBase: A child container failed during start
java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].StandardContext[]]
    at java.util.concurrent.FutureTask.report(FutureTask.java:122)
    at java.util.concurrent.FutureTask.get(FutureTask.java:188)
    at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1123)
    at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:799)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
    at java.util.concurrent.FutureTask.run(FutureTask.java:262)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].StandardContext[]]
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
    ... 6 more
Caused by: java.lang.NoSuchMethodError: javax.servlet.ServletContext.addServlet(Ljava/lang/String;Ljavax/servlet/Servlet;)Ljavax/servlet/ServletRegistration$Dynamic;
    at org.springframework.boot.context.embedded.ServletRegistrationBean.onStartup(ServletRegistrationBean.java:166)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext$1.onStartup(EmbeddedWebApplicationContext.java:214)
    at org.springframework.boot.context.embedded.tomcat.ServletContextInitializerLifecycleListener.lifecycleEvent(ServletContextInitializerLifecycleListener.java:54)
    at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
    at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5355)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    ... 6 more
4

15 回答 15

29

如果您想找出从哪里加载类,请尝试

java -verbose:class -jar foo.jar | grep javax.servlet.ServletContext

foo.jarGradle 或 Maven 生成的胖 JAR在哪里。例如,ServletContext可以从servlet-apiJDK 扩展目录中的旧 JAR 中读取该类,而不是从您的 Maven 或 Gradle 依赖项中读取该类。

该命令的输出看起来像这样......

$ java -verbose:class -jar build/libs/foo-0.2.3.jar | grep javax.servlet.ServletContext
[Loaded javax.servlet.ServletContext from jar:file:.../build/libs/foo-0.2.3.jar!/lib/javax.servlet-api-3.1.0.jar!/]
[Loaded javax.servlet.ServletContextListener from jar:file:.../build/libs/foo-0.2.3.jar!/lib/javax.servlet-api-3.1.0.jar!/]
[Loaded javax.servlet.ServletContextAttributeListener from jar:file:.../build/libs/foo-0.2.3.jar!/lib/javax.servlet-api-3.1.0.jar!/]
于 2015-02-19T18:41:21.747 回答
27

我解决了它,不包括传递的 servlet-api 依赖项。

就我而言,它是 com.github.isrsal:spring-mvc-logger

<dependency>
    <groupId>com.github.isrsal</groupId>
    <artifactId>spring-mvc-logger</artifactId>
    <version>0.2</version>
    <exclusions>
        <exclusion>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
        </exclusion>
    </exclusions>
</dependency>
于 2014-10-07T09:12:13.287 回答
23

梯度解决方案。

我在我的 lib jar 中遇到了类似的问题,由于某种原因,它带来了一个旧版本的 javax.servlet.ServletContext,它后来由我的 spring-boot 模块而不是它自己提供的类加载,从而导致 NoSuchMethodError

我通过编辑我的 lib 模块的 build.gradle 来修复它:

configurations {
    provided.all*.exclude group: 'javax.servlet'
}
于 2015-04-12T12:22:21.453 回答
9

对于无法通过 exclude 解决的其他任何人servlet-api,这里有一个替代方案:

事实证明 Spring Boot 默认为 Tomcat 8。如果您正在运行不同版本的 Tomcat 并希望修复此错误,只需将您的 tomcat 版本添加到 pom 属性中:

<properties>
    <tomcat.version>7.0.63</tomcat.version>
</properties> 
于 2015-08-19T17:33:29.207 回答
8

我在 spring-boot webapp 中有这个,只在部署服务器中(在我的本地机器上运行良好)。我通过添加解决它:

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

http://docs.spring.io/spring-boot/docs/current/reference/html/howto-traditional-deployment.html

于 2015-05-28T09:17:06.417 回答
7

我在测试期间尝试启动我的 Spring Boot 服务器时遇到了这个问题(使用 gradle + spock)。我将问题追溯到wiremock库。

这修复了它:

testCompile('com.github.tomakehurst:wiremock:1.58') {
    exclude module: 'servlet-api' // this exclude fixed it
}

供参考

gradle dependencies

显示(删节):

\--- com.github.tomakehurst:wiremock:1.58
     +--- org.mortbay.jetty:jetty:6.1.26
          +--- org.mortbay.jetty:jetty-util:6.1.26
          \--- org.mortbay.jetty:servlet-api:2.5-20081211

古老的 (2008) org.mortbay.jetty:servlet-apijar 包含一个ServletContext与 spring boot 1.3.2 版本不兼容的版本(至少在 1.2.6 之前可以正常工作)。

于 2016-02-23T01:01:16.217 回答
6

我正在使用 Gradle,什么对我有用:

configurations {
    all*.exclude group: '', module: 'servlet-api'
}

它以所需的方式修剪依赖树。

于 2015-04-16T13:11:52.400 回答
6

我正在使用 Spring-boot 运行 Hadoop 2.7.2,以下 Hadoop 依赖项使用javax.servlet阻止了嵌入式 tomcat 版本的启动。我的 POM 中的以下排除解决了这个问题

                                    <dependency>
                                    <groupId>org.apache.hadoop</groupId>
                                    <artifactId>hadoop-hdfs</artifactId>
                                    <version>2.7.2</version>
                                    <exclusions>
                                        <exclusion>
                                            <artifactId>servlet-api</artifactId>
                                            <groupId>javax.servlet</groupId>
                                        </exclusion>
                                    </exclusions>
                                </dependency>
                                <dependency>
                                    <groupId>org.springframework.data</groupId>
                                    <artifactId>spring-data-hadoop-boot</artifactId>
                                    <version>2.3.0.RELEASE-hadoop26</version>
                                    <exclusions>
                                        <exclusion>
                                            <artifactId>servlet-api</artifactId>
                                            <groupId>javax.servlet</groupId>
                                        </exclusion>
                                    </exclusions>
                                </dependency>

                                <dependency>
                                    <groupId>org.apache.hadoop</groupId>
                                    <artifactId>hadoop-common</artifactId>
                                    <version>2.7.2</version>
                                    <exclusions>
                                        <exclusion>
                                            <artifactId>slf4j-log4j12</artifactId>
                                            <groupId>org.slf4j</groupId>
                                        </exclusion>
                                        <exclusion>
                                            <artifactId>servlet-api</artifactId>
                                            <groupId>javax.servlet</groupId>
                                        </exclusion>
                                    </exclusions>
                                </dependency>
于 2016-07-09T08:18:34.050 回答
4

根据这个解决方案: https ://stevewall123.wordpress.com/2015/04/17/spring-boot-application-and-tomcat-error-a-child-container-failed-during-start/

您可以通过设置“tomcat.version”属性来更改 Tomcat 版本:

ext['tomcat.version'] = '7.0.63' //my version of Tomcat

dependencies {
    compile 'org.springframework.boot:spring-boot-starter-web'
}

感谢那篇文章的作者,它对我有用。

干杯:)

于 2016-05-08T10:17:27.903 回答
4

除了知道它以某种方式进入我的类路径之外,我无法找到有问题的参考,所以这是我为使用 eclipse 的懒惰开发人员提供的 2 美分:

向下滚动项目树下的 maven 依赖项列表(通常在 Java 资源 -> 库 -> Maven 依赖项下),跟踪您希望从打包的 JAR 中排除的有问题的添加 jar,右键单击它 -> 选择 Maven -> 排除马文神器!瞧 - 在引用它的依赖项下,会自动将排除项添加到您的 pom 中。

我的顺便说一句是 jcifs ......

        <dependency>
        <groupId>org.codelibs</groupId>
        <artifactId>jcifs</artifactId>
        <version>1.3.18.2</version>
        <exclusions>
            <exclusion>
                <artifactId>servlet-api</artifactId>
                <groupId>javax.servlet</groupId>
            </exclusion>
        </exclusions>
    </dependency>

祝你好运!

于 2016-11-10T07:37:09.107 回答
3

如果您使用 STS 并且已将 Groovy 库添加到您的项目(项目属性 -> Java 构建路径 -> 库),请确保选择“否,仅包含 groovy-all”选项。“是的,包括 groovy-all 和 bsf.jar ...,servlet-2.4.jar”的另一个选项添加了 servlet-2.4.jar,它与嵌入式 tomcat8 类冲突,导致此问题。

于 2016-03-24T07:32:08.363 回答
3

我在我的项目中使用 Jetty 并得到了同样的错误。我的快速解决方案是从 Maven 依赖项中排除嵌入式 Tomcat:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-ws</artifactId>
    <version>1.2.0.RELEASE</version>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>
于 2016-04-20T14:54:09.127 回答
2

mvn dependency:tree没有servlet-api.jar在我的类路径上显示,但右键单击项目(在 Eclipse 中)并转到构建路径/配置构建路径显示我的默认工作区 JRE,JDK 1.7.0_51,在其jre/lib/ext目录中有该 jar(至少在我的安装)。我尝试将其从类路径中删除,但未能成功。@Pedro 将 tomcat 版本强制为 7的解决方案有效。安装最新版本的 Java 7 也是如此:JDK 1.7.0_79。

于 2016-01-03T16:06:46.667 回答
1

我也遇到了这个错误。我有一个 Maven/Spring MVC/Spring Boot 项目。我使用 IntelliJ 作为 IDE,每当我向 POM.xml 添加新的依赖项时,IDE 都会更改 .iml 文件(如预期的那样),但奇怪的是它将以下行移至文件顶部:

<orderEntry type="library" name="Java EE 6-Java EE 6" level="project" />

一旦发生这种情况,我的项目将无法编译,并且出现相同的错误:

java.lang.NoSuchMethodError: javax.servlet.ServletContext.getVirtualServerName()Ljava/lang/String;

只需将 Java EE 的 orderEntry 移回底部,错误就会消失,我可以再次编译。

于 2016-04-18T17:16:17.133 回答
0

为了快速解决,我已经从 lib 中手动删除了 servlet-api.jar,然后构建了应用程序并且它可以工作。虽然,理想情况下,正如 Kumetix 所建议的那样,应该需要仔细检查导致它加载到类路径中的依赖项。

于 2015-08-20T10:34:27.350 回答