簡體   English   中英

在運行 Spring MVC 應用程序時獲取 NoSuchMethodError:Spring 中的 javax.servlet.ServletContext.addServlet

[英]Getting NoSuchMethodError: javax.servlet.ServletContext.addServlet in Spring Boot while running a Spring MVC application

當我嘗試使用 Spring 引導運行 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

如果你想找出加載類的位置,試試吧

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

其中foo.jar是Gradle或Maven生產的胖JAR。 例如,可以從JDK擴展目錄中的舊servlet-api JAR而不是Maven或Gradle依賴項中讀取ServletContext類。

命令的輸出看起來像這樣......

$ 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,后來由我的spring-boot模塊而不是它自己提供的類加載,導致NoSuchMethodError

我通過編輯我的lib模塊的build.gradle來修復它:

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> 

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

我在測試期間嘗試啟動彈簧啟動服務器時遇到此問題(使用gradle + spock)。 我將問題追溯到了線索庫。

這解決了它:

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 jar包含一個版本的ServletContext ,它與Spring引導版本1.3.2不兼容(工作正常至少高達1.2.6)。

我在使用Gradle以及對我有用的東西:

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

它以期望的方式修剪了依賴樹。

我使用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>

根據這個解決方案: 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'
}

由於該文章的作者,它對我有用。

干杯:)

如果您正在使用STS並且已將Groovy庫添加到項目中(項目屬性 - > Java構建路徑 - >庫),請確保選擇“否,僅包括groovy-all”選項。 “是,包括groovy-all和bsf.jar ...,servlet-2.4.jar”的另一個選項添加了servlet-2.4.jar,它與嵌入式tomcat8類沖突導致了這個問題。

我在我的項目中使用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>

我無法追蹤有問題的引用,除非知道它以某種方式進入我的類路徑所以這是我使用eclipse的懶惰開發人員的2美分:

向下滾動項目樹下的maven依賴項列表(通常在Java Resources - > Libraries - > Maven Dependencies下),跟蹤要從打包的JAR中排除的有問題的jar,右鍵單擊它 - >選擇Maven - > Exclude Maven神器! 瞧 - 自動排除將被添加到您的pom右下方引用它。

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

祝好運!

mvn dependency:tree沒有在我的類路徑中顯示servlet-api.jar ,但右鍵單擊項目(在Eclipse中)並轉到Build Path / Configure Build Path顯示我的默認工作區JRE,JDK 1.7.0_51,有jar的jre/lib/ext目錄(至少在我的安裝中)。 我試過並且沒能將它從我的類路徑中刪除。 @ Pedro強制將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 for Java EE移回底部,錯誤消失了,我可以再次編譯。

為了快速解決,我已經從lib中手動刪除了servlet-api.jar,而不是構建應用程序並且它可以工作。盡管如此,理想情況下,如Kumetix所建議的,應該仔細檢查直到導致它在類路徑中加載的依賴關系。

對我來說,這是解決方案;

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

將 servlet-api 的依賴添加到 pom.xml

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM