ClassCastException:DispatcherServlet 不能强制转换为 Servlet

Posted

技术标签:

【中文标题】ClassCastException:DispatcherServlet 不能强制转换为 Servlet【英文标题】:ClassCastException: DispatcherServlet cannot be cast to Servlet 【发布时间】:2013-07-21 21:06:52 【问题描述】:

我使用 maven-eclipse 创建了一个新的 Spring MVC 项目,并抛出以下错误:

(我从 *** 中尝试了一些解决方案,但在我的情况下不起作用。我找不到 pom.xml 的一些问题。我为 servlet-api 添加了提供的范围并尝试了它也不起作用。)

SEVERE: Servlet /Remindem threw load() exception
java.lang.ClassCastException: org.springframework.web.servlet.DispatcherServlet 
  cannot be cast to javax.servlet.Servlet

我的pom.xml如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.org</groupId>
<artifactId>Remindem</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>

<name>Remindem</name>
<url>http://maven.apache.org</url>

<dependencies>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.0.1</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.maven</groupId>
        <artifactId>maven-plugin-api</artifactId>
        <version>2.0</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>3.8.1</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>3.6.8.Final</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>4.0.0.Beta2</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.6</version>
    </dependency>
    <dependency>
        <groupId>javassist</groupId>
        <artifactId>javassist</artifactId>
        <version>3.12.1.GA</version>
    </dependency>
    <dependency>
        <groupId>javax.mail</groupId>
        <artifactId>mail</artifactId>
        <version>1.4</version>
    </dependency>

    <!-- Spring framework -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring</artifactId>
        <version>2.5.6</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>2.5.6</version>
        <scope>compile</scope>

    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>3.2.3.RELEASE</version>
        <scope>compile</scope>
    </dependency>


    <!-- Spring MVC framework -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>2.5.6</version>
        <scope>compile</scope>
    </dependency>

    <!-- JSTL -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
        <version>1.1.2</version>
    </dependency>

    <dependency>
        <groupId>taglibs</groupId>
        <artifactId>standard</artifactId>
        <version>1.1.2</version>
    </dependency>

    <dependency>
        <groupId>org.apache.tomcat</groupId>
        <artifactId>tomcat-api</artifactId>
        <version>7.0.19</version>
    </dependency>
</dependencies>

<build>
    <plugins>
<plugin>
    <groupId>org.apache.tomcat.maven</groupId>
    <artifactId>tomcat7-maven-plugin</artifactId>
    <version>2.0</version>
    <configuration>
      <url>http://localhost:8080/Remindem</url>
    </configuration>
  </plugin>
    </plugins>
</build>

我的web.xml如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

<display-name>Remindem</display-name>
<session-config>
    <session-timeout>
        30
    </session-timeout>
</session-config>
<welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

     <servlet>
        <servlet-name>svn</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                /WEB-INF/SpringAppServlet.xml               
            </param-value>
        </init-param>
    <load-on-startup>1</load-on-startup>
</servlet> 

 <servlet-mapping>
    <servlet-name>svn</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping> 

 <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

</web-app>

【问题讨论】:

【参考方案1】:

改变

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.0.1</version>
    <scope>compile</scope>
</dependency>

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

provided 有这样的描述:

这很像 compile,但表示您期望 JDK 或 容器在运行时提供依赖。例如,当 为 Java 企业版构建一个 Web 应用程序,您将 将 Servlet API 和相关 Java EE API 的依赖设置为 提供范围是因为 Web 容器提供了这些类。这 范围仅在编译和测试类路径上可用,并且是 不及物。

来自mavendocs。您基本上是在告诉 Maven 提供用于编译的 jar,但是在运行时使用其他一些 servlet 容器的 jar。

【讨论】:

我改了。但它仍然会引发同样的错误。我需要改变什么吗? @user 您使用的是哪个容器版本?尝试在 Eclipse 和 Maven 中清理和重建您的项目。 我不确定我使用的是哪个容器版本。但是,这就是我跑步的方式。我运行 maven clean, maven install 然后做一个 maven 构建,我将目标提供为 tomcat:run 您的 maven tomcat 依赖项有什么需要吗?如果没有,请将其删除。您的 Servlet jar 版本出现问题。 另外,请尽可能更新您的春季版本。【参考方案2】:

在您的情况下, ClassCastException 似乎是因为类被不同的类加载器加载。比如说,您错误地将 servlet-api.jar 包含在您的 WEB-INF/lib 中,并且您已将 PARENT_LAST 设置为您的 webapp 类加载器。如果您在像 WAS 这样的应用程序服务器上运行,这意味着您正在使用一个类加载器(顶部的某个类加载器)和实现(servlet-api jar 只是一个 eg)与底部的另一个类加载器加载接口。

【讨论】:

【参考方案3】:

将范围保持为“已提供”并尝试将该 jar 保存在 tomcat/lib 文件夹中。这是因为各个战争的每个类加载器都试图单独加载自己的 Servlet-api 类,而应用程序类加载器在容器级别加载 Servlet-api 类。

因此,如果您可以将 jar 移动到 CATALINA_HOME/lib。您只需要由应用程序类加载器加载的类集,并且所有战争都将引用相同的版本。

scope 'provided' 向战争级别的类加载器传达此所需的类已由应用程序类加载器加载,并坚持其战争级别的类加载器可能不需要为其创建单独的实例或版本,从而导致类转换异常

【讨论】:

【参考方案4】:

您使用的是哪个应用服务器?我认为 Servlet jars 文件应该由您的应用程序服务器提供。

【讨论】:

我做了一个 maven 构建并提供目标为:tomcat:run 由 Sotirios Delimanolis 回答,这正是我想说的。 org.springframeworkspring-context3.2.3.RELEASE编译 删除 compile 并尝试,我只是将你的 pom 与我的工作区 pom 进行比较。

以上是关于ClassCastException:DispatcherServlet 不能强制转换为 Servlet的主要内容,如果未能解决你的问题,请参考以下文章

PySpark:java.lang.ClassCastException

应用 PathProperties 后的 ClassCastException

MIUI 11/12 主题切换导致 LifeCycleException、ClassCastException

ClassCastException 发生在 onRestoreInstanceState

Java HashMap导致ClassCastException

用 Java Lambda 编写的 Spark UDF 引发 ClassCastException