Получение NoSuchMethodError: javax.servlet.ServletContext.addServlet в Spring Boot при запуске приложения Spring MVC

Я получаю исключение ниже, когда я пытаюсь запустить приложение Spring MVC, используя Spring boot...

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

16 ответов

Если вы хотите узнать, откуда загружается класс, попробуйте

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

где foo.jar это толстый JAR, произведенный Gradle или Maven. Например, ServletContext класс может быть прочитан от старшего servlet-api JAR в каталоге расширений JDK вместо ваших зависимостей 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!/]

Я решил это за исключением транзитивной зависимости 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>

Gradle решение.

У меня была похожая проблема в моем lib jar, которая по какой-то причине принесла старую версию javax.servlet.ServletContext, которая позже была загружена моим подпружиненным загрузочным модулем вместо собственного предоставленного класса, что вызвало NoSuchMethodError

Я исправил это, отредактировав build.gradle моего модуля lib:

configurations {
    provided.all*.exclude group: 'javax.servlet'
}

Для тех, кто не может решить эту проблему, исключив servlet-api Вот альтернатива:

По умолчанию Spring Boot оказывается Tomcat 8. Если вы работаете с другой версией Tomcat и хотите исправить эту ошибку, просто добавьте версию tomcat в свойства pom:

<properties>
    <tomcat.version>7.0.63</tomcat.version>
</properties> 

У меня это было в весеннем загрузочном веб-приложении, только на сервере развертывания (работало нормально на моей локальной машине). Я решаю это, добавив:

<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

У меня была эта проблема при попытке запустить мой весенний загрузочный сервер во время тестов (используя gradle + spock). Я проследил проблему до библиотеки Wiremock.

Это исправило это:

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

FYI

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-api банка содержит версию ServletContext это несовместимо с версией 1.3.2 пружинной загрузки (работало нормально, по крайней мере, до 1.2.6).

Я использовал Gradle и что сработало для меня:

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

Он обрезал дерево зависимостей по желанию.

Я работал с Hadoop 2.7.2 с использованием Spring-boot, в следующих зависимостях 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>

Согласно этому решению: https://stevewall123.wordpress.com/2015/04/17/spring-boot-application-and-tomcat-error-a-child-container-failed-during-start/

Вы можете изменить версию Tomcat, установив свойство "tomcat.version":

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

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

это работает для меня, благодаря автору этой статьи.

Ура:)

Я не мог отследить проблемную ссылку, за исключением того, что знал, что она каким-то образом попадает в мой путь к классам, поэтому вот мои 2 цента для ленивых разработчиков, использующих eclipse:

Прокрутите список зависимостей maven в дереве проекта (обычно в разделе Ресурсы Java -> Библиотеки -> Зависимости Maven), отследите проблемный добавленный jar, который вы хотите исключить из упакованного JAR-файла, щелкните правой кнопкой мыши по нему -> выберите Maven -> Exclude Maven Артефакт! Вуаля - автоматически исключение будет добавлено к вашей поме прямо под зависимостью, которая ссылается на него.

Мой BTW был 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>

Удачи!

Я использую Jetty в моем проекте и получил ту же ошибку. Моим быстрым решением было исключить встроенный Tomcat из зависимости Maven:

<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>

Если вы используете STS и добавили библиотеку Groovy в свой проект (Свойства проекта -> Путь сборки Java -> Библиотеки), убедитесь, что вы выбрали опцию "Нет, только groovy-all". Другой вариант "Да, включая groovy-all и bsf.jar..., servlet-2.4.jar" добавляет servlet-2.4.jar, который конфликтует со встроенными классами tomcat8, что приводит к этой проблеме.

mvn dependency:tree не раскрыл servlet-api.jar на моем пути к классам, но щелкнув правой кнопкой мыши по проекту (в Eclipse) и перейдя в Build Path / Configure Build Path, я обнаружил, что в моем JREK 1.7.0_51 в рабочей области по умолчанию эта банка была jre/lib/ext каталог (по крайней мере, в моей установке). Я попытался и не смог удалить его из моего classpath. @ Решение Педро по принуждению версии Tomcat к 7 сработало. Так же была установлена ​​последняя версия Java 7: JDK 1.7.0_79.

Я тоже сталкивался с этой ошибкой. У меня есть проект 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;

просто переместив orderEntry для Java EE вниз, ошибка исчезнет, ​​и я смогу скомпилировать еще раз.

Для меня это было решением;

https://mkyong.com/java/servlet-api-2-5-jar-jar-not-loaded/

добавление зависимости servlet-api к pom.xml

Для быстрого решения я удалил servlet-api.jar вручную из lib и затем собрал приложение, и оно работает. Хотя, в идеале, как рекомендует Kumetix, нужно тщательно изучить до зависимости, которая заставляет его загружаться в classpath.

Другие вопросы по тегам