Spring 6.0.5部署Tomcat 8.5.81时DispatcherServlet类型转换异常求助
Spring 6.0.5部署Tomcat 8.5.81的ClassCastException问题分析与解决
场景说明
在Tomcat 8.5.81上部署Spring 6.0.5应用,通过web.xml配置org.springframework.web.servlet.DispatcherServlet,运行时抛出类转换异常。
相关配置
web.xml配置
<servlet> <servlet-name>dispatcher</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> </servlet> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/dispatcher-config.xml</param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
dispatcher-config.xml配置
<mvc:annotation-driven/> <mvc:resources mapping="/resources/**" location="/resources/"/> <context:component-scan base-package="org.mainPackage" /> <context:annotation-config/> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix"> <value>/WEB-INF/views/</value> </property> <property name="suffix"> <value>.jsp</value> </property> </bean>
pom.xml相关依赖
<properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <java.version>17</java.version> <tomcat.version>8.5.81</tomcat.version> <servlet-api.version>3.1.0</servlet-api.version> </properties> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>6.0.5</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>6.0.5</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>6.0.5</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>jakarta.servlet.jsp.jstl</groupId> <artifactId>jakarta.servlet.jsp.jstl-api</artifactId> <version>3.0.0</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency>
异常信息
javax.servlet.ServletException: Class [org.springframework.web.servlet.DispatcherServlet] is not a servlet 根因: java.lang.ClassCastException: class org.springframework.web.servlet.DispatcherServlet cannot be cast to class javax.servlet.Servlet (org.springframework.web.servlet.DispatcherServlet is in unnamed module of loader org.apache.catalina.loader.ParallelWebappClassLoader @4ac6da24; javax.servlet.Servlet is in unnamed module of loader java.net.URLClassLoader @28c97a5)
异常原因
- 核心API包名不兼容:Spring 6基于Jakarta EE 9+规范,依赖的是
jakarta.servlet.Servlet接口;而Tomcat 8.5.x属于传统Servlet容器,使用的是javax.servlet.ServletAPI。两者属于不同的包空间,类加载器无法将实现Jakarta接口的DispatcherServlet转换为Tomcat期望的javax版本接口。 - 依赖混乱与版本不匹配:
- pom.xml同时引入了javax版本的Servlet API和Jakarta版本的JSTL,包名冲突导致类加载异常;
- Java编译级别设置为1.8,但Spring 6要求最低Java 17,编译与运行环境不匹配;
- 同时手动引入Spring核心依赖和
spring-boot-starter-web,存在依赖重复或版本不一致风险。
解决方案
方案一:升级Tomcat版本(推荐)
Spring 6要求Servlet 5.0+(对应Jakarta EE 9),只有Tomcat 10.x及以上版本支持Jakarta Servlet API(包名从javax.servlet改为jakarta.servlet)。将Tomcat升级到10.1.x(兼容Java 17,与Spring 6完美匹配),可直接解决核心包名冲突问题。
方案二:降级Spring版本(仅当无法升级Tomcat时使用)
若必须保留Tomcat 8.5.x,需将Spring版本降级到5.3.x(Spring 5.x基于javax.servlet API,与Tomcat 8.5完全兼容),同时将所有Spring相关依赖版本统一为5.3.x系列。
配套依赖配置调整
- 统一Java编译级别:
修改pom.xml的编译配置,确保与运行环境一致(以Java 17为例):<properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> <java.version>17</java.version> <!-- 若用Tomcat 10.x,使用Jakarta Servlet版本 --> <jakarta.servlet.version>5.0.0</jakarta.servlet.version> </properties> - 清理冲突依赖:
- 若升级Tomcat到10.x,移除所有
javax.servlet相关依赖,替换为Jakarta版本:<!-- 移除javax.servlet-api和javax.servlet:jstl --> <dependency> <groupId>jakarta.servlet</groupId> <artifactId>jakarta.servlet-api</artifactId> <version>${jakarta.servlet.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.glassfish.web</groupId> <artifactId>jakarta.servlet.jsp.jstl</artifactId> <version>3.0.1</version> </dependency> - 移除重复的Spring依赖:如果使用
spring-boot-starter-web,无需手动引入spring-web、spring-core、spring-context,starter会自动管理这些依赖,避免版本冲突。
- 若升级Tomcat到10.x,移除所有
- 更新web.xml命名空间(仅Tomcat 10.x需做):
将web.xml的根命名空间替换为Jakarta EE的标准命名空间:<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd" version="5.0"> <!-- 原servlet、listener等配置内容保持不变 --> </web-app>
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

