获取NoSuchMethodError:javax.servlet.ServletContext.getVirtualServerName()

41

我在Tomcat 8部署服务时遇到问题,出现以下错误:

Caused by: java.lang.NoSuchMethodError: javax.servlet.ServletContext.getVirtualServerName()Ljava/lang/String; at org.apache.tomcat.websocket.server.WsServerContainer.(WsServerContainer.java:149) at org.apache.tomcat.websocket.server.WsSci.init(WsSci.java:131) at org.apache.tomcat.websocket.server.WsSci.onStartup(WsSci.java:47) at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5244) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) ... 10 more

getVirtualServerName方法是在Servlet 3.1中引入的。从我的 jar中提取MANIFEST.MF后,我得到了以下详细信息:

Specification-Title: Java API for Servlets 
Specification-Version: 3.1 
Specification-Vendor: Sun Microsystems, Inc. 
Implementation-Title: javax.servlet 

这意味着它拥有3.1版本。那么是否还有其他原因导致此错误?请帮忙。


你是从Eclipse运行吗?还是……请告诉我们更多关于你的环境、应用和设置。 - MrSimpleMind
1
我也是这么想的,这就是我问环境的原因... 你使用pom.xml吗?也许你应该将属性更改为<tomcat.version>xxxx</tomcat.version>以适用于Tomcat 8...? - MrSimpleMind
@MrSimpleMind 是的,我正在使用POM。但是我还没有声明 <tomcat.version>。所以如果我不声明它,它会默认使用什么? - Rahman
这是一个Spring解决方案吗?我认为默认情况下它会运行Tomcat 7..所以如果你想运行8xxx..那么需要添加该信息。 - MrSimpleMind
@MrSimpleMind 是的,它使用了Spring框架。 - Rahman
显示剩余3条评论
11个回答

27

检查您所有的Maven(或等效)依赖项,并确保您 - 或更可能是另一个依赖项 - 没有拉取优先于Tomcat 8中的内容的javax.servlet / servlet-api的3.1版本之前的版本。如果您手动部署,请确保您没有手动将任何servlet-api JAR文件复制到Tomcat本身中。

参见:https://dev59.com/dWAf5IYBdhLWcg3w_G2r#26232535


6
使用命令行在项目根目录下运行 mvn dependency:tree 命令,查找输出中的 servlet-api 依赖项,通常是版本为2.?。在 pom 文件中添加以下内容将其排除在依赖项之外:{ <exclusion> <artifactId>servlet-api</artifactId> <groupId>javax.servlet</groupId> </exclusion>}。请注意,此操作旨在定位引起问题的依赖项,并将其从项目中移除,以避免冲突或错误。 - user1412523
@user1412523 谢谢!这对我解决了问题。我的依赖项是 google-oauth-client-jetty。 我把它移除了,因为我不需要它,并且现在它又可以工作了。 - A.W.
我的依赖项是 hadoop-common(2.9.2) - Fabich
mvn dependency:tree | grep servlet-api - kinjelom
谢谢@user1412523,你的评论非常有用。我终于解决了我的apache fop-transcoder-allinone 2.4依赖问题,现在可以继续进行了。 - Sir Beethoven
这里有另一种尝试定位冲突源的方法...运行您的构建,然后展开war文件或找到构建所在的文件夹(在maven中可能是target/xx),然后找到WEB-INF/lib文件夹并使用此Unix脚本查找包含名称为“ServletContext”的类的jar文件。您可能会得到错误的结果,但它会引导您朝着正确的方向前进: find . -name "*.jar" -exec grep -l ServletContext {} \; - AndrewL

22

在 Servlet 3.1 中,添加了方法 getVirtualServerName 到 ServletContext 中。请查看 Java 文档中的方法 getVirtualServerName

此问题有三个主要原因:

  1. 您的 Servlet 版本低于 3.1。

  2. 某些其他 jar 中具有低于 3.1 版本的 Servlet。

  3. 您的 Tomcat 版本低于 8。

为解决此问题,您可以尝试以下方法:

I. 检查您的 pom.xml 文件是否包含以下代码。

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

如果您的pom.xml文件有以上代码,则仍然会出现该问题。您可以采用第二种方法。
II. 检查您的其他jar是否引用了javax.servlet-api jar。例如,org.apache.santuario引用了javax.servlet-api jar。pom.xml文件:
<dependency>  
    <groupId>org.apache.santuario</groupId>  
    <artifactId>xmlsec</artifactId>  
    <version>1.4.3</version>   
</dependency> 

但是当你查看Maven依赖项时,它引用了版本为2.3的javax.servlet-api jar,比3.1旧。

enter image description here

所以您应该排除2.3版本。pom.xml:

<!-- exclude servlet-api 2.3 jar-->  
<dependency>  
    <groupId>org.apache.santuario</groupId>  
    <artifactId>xmlsec</artifactId>  
    <version>1.4.3</version>  
    <exclusions>  
        <exclusion>  
            <groupId>javax.servlet</groupId>  
            <artifactId>servlet-api</artifactId>  
        </exclusion>  
    </exclusions>  
</dependency>  

<!-- servlet-api 3.1 version has getVirtualServerName() -->  
<dependency>  
    <groupId>javax.servlet</groupId>  
    <artifactId>javax.servlet-api</artifactId>  
    <version>3.1.0</version>  
</dependency> 

III. Spring Boot默认使用Tomcat 7运行。因此,如果您想使用Tomcat 8而不是Tomcat 7,请在pom.xml中添加以下代码:

   <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <tomcat.version>8.5.5</tomcat.version>
    </properties>

可以不排除传递依赖项,但要包含正确的版本。Maven会选择在图中更接近的版本。 - senyor

10

在更新IntelliJ之后,我在使用maven时遇到了错误。

我可以使用maven运行测试,但无法从我的IDE中运行。

我通过删除./ideaproject.iml文件并重新加载项目来解决这个问题。


5

如果您使用了这个依赖:

<dependency>
    <groupId>com.google.oauth-client</groupId>
    <artifactId>google-oauth-client-jetty</artifactId>
    <version>1.23.0</version>
</dependency>

那么请按照以下方式进行排除:

<dependency>
    <groupId>com.google.oauth-client</groupId>
    <artifactId>google-oauth-client-jetty</artifactId>
    <version>1.23.0</version>
    <exclusions>
        <exclusion>
            <artifactId>servlet-api</artifactId>
            <groupId>org.mortbay.jetty</groupId>
        </exclusion>
    </exclusions>
</dependency>

太好了,那正是我的错误,你是怎么知道的呢? - Rigoxls
@Rigoxls 我记得我在使用Google客户端API和Spring框架时遇到了这个问题。 - yuen26

4

Spring Boot默认运行Tomcat 7,您需要在pom.xml中覆盖Maven构建的tomcat.version。请参见以下内容以运行Tomcat 8.0.30。

<properties>
  <tomcat.version>8.0.30</tomcat.version>
</properties>

应该能解决你的问题。

2

解决方案 我在使用从网站上下载并解压的Tomcat时,遇到了与Java 8相关的问题。

我的问题得到了解决,因为有一个额外的servlet-api.jar文件被捆绑在一起。它来自于 /Library/Java/Extensions/servlet-api.jar

要在您的系统中找到它,您可以使用以下命令: sudo find / -name servlet-api.jar

将其备份到其他位置后删除它。

我按照以下步骤进行了安装: https://gist.github.com/ddanailov-nmdp/c97aba2ca926b9627f6b4f7174083a32


1
假设您在Eclipse中运行应用程序时遇到了这个问题。 请使用依赖层次结构视图在pom.xml中搜索servlet-api。

0

我附上gradle风格的依赖代码。

dependencies {
    compileOnly("javax.servlet:javax.servlet-api:3.1.0")

1
请不要只发布代码作为答案,还要提供解释你的代码是做什么的以及它如何解决问题。带有解释的答案通常更有帮助和更高质量,并且更有可能吸引赞成票。 - Mark Rotteveel

0
在我的情况下,我添加了虚拟机选项-verbose:class来查找错误的jar包,并排除了冲突的jar包,然后添加了较高版本的javax.servlet-api(3.1.0),问题得到了解决。

0

经过长时间的煎熬和筛选所有这些stackoverflow答案,最终对我起作用的唯一方法是从tomcat8降级到tomcat7。我知道这不是一个理想的解决方案,也许只是一个新安装的tomcat解决了我的问题。如果其他方法都失败了,可以尝试一下这个。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接