You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring MVC项目Dispatcher Servlet未初始化引发404错误求助

Spring MVC应用部署后DispatcherServlet未初始化,请求返回404

我正在跟随Udemy的Spring与Spring Boot课程搭建Web应用,使用Tomcat 9.0和Spring Boot Suite部署,日志显示应用已成功部署到INFORMAZIONI: Deploying web application directory [C:\Users\Fabrizio\Documents\Spring\Udemy - Guida Completa\apache-tomcat-9.0.71\webapps\ROOT],访问http://localhost:8080可正常显示Tomcat首页,但访问http://localhost:8080/rest/welcome时出现404错误。

课程视频中的控制台会输出Initializing Spring DispatcherServlet 'dispatcher'日志,但我的控制台没有该日志,推测Dispatcher Servlet未初始化是导致控制器无法处理请求的原因。已尝试删除并重启服务器,但问题依旧。

已编写的类

WebConfig.java

package it.fogliafabrizio.corso.web;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "it.fogliafabrizio.corso.web.controller") //自动检测控制器并将其作为bean管理
public class WebConfig {

}

AppInitializer.java

package it.fogliafabrizio.corso.web;

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.FrameworkServlet;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        // TODO 自动生成方法存根
        return null;
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        /* 指定用于访问Web应用所有配置的类 */
        return new Class<?>[] {WebConfig.class}; //返回配置类的泛型Class数组
    }

    @Override
    protected String[] getServletMappings() {
        /* 指定DispatcherServlet在应用中需要拦截的路径 */
        
        return new String[]{"/"}; //应用收到的所有请求都需被处理
    }

    @Override
    /* 右键 > 源码 > 重写/实现方法
     * AbstractDispatcherInitializer -> 找到接收WebApplicationContext的方法
     */
    protected FrameworkServlet createDispatcherServlet(WebApplicationContext servletAppContext) {
        /* 创建DispatcherServlet实例,传入应用上下文
         * 设置setThrowExceptionIfNoHandlerFound为true,使Web应用抛出异常而非返回404错误
         * 并返回该实例
         */
        DispatcherServlet ds = new DispatcherServlet(servletAppContext);
        ds.setThrowExceptionIfNoHandlerFound(true);
        return ds;
    }
    
    

}

控制器示例:WelcomeRestController.java

package it.fogliafabrizio.corso.web.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/rest")
public class WelcomeRestController {
    
    @RequestMapping("/welcome")
    public String welcome() {
        return "{message: Welcome}"; //示例JSON
    }

}

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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>it.fogliafabrizio.corso.web</groupId>
  <artifactId>corsospringweb</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
  <name>corsospringweb</name>
  
  
  <dependencies>
    <dependency>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <version>3.3.2</version>
     </dependency>
     
     <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>6.0.4</version>
    </dependency>
    
    <dependency>
        <!-- 核心模块 -->
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>6.0.4</version>
    </dependency>
    
    <dependency>
        <!-- Beans模块 -->
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>6.0.4</version>
    </dependency>
    
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>6.0.4</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>6.0.4</version>
    </dependency>
    
    <dependency>
        <groupId>jakarta.servlet</groupId>
        <artifactId>jakarta.servlet-api</artifactId>
        <version>6.0.0</version>
        <scope>provided</scope>
    </dependency>


    <dependency>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.10.1</version>
    </dependency>
    
  </dependencies>
  <build>
      <plugins>
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <version>3.3.2</version>
            <configuration>
                <failOnMissingWebXml>false</failOnMissingWebXml>
            </configuration>
         </plugin> 
         
         <plugin>
             <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.10.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
         </plugin>
      </plugins>
  </build>
</project>

问题排查与解决方案

1. 版本兼容性问题

Spring 6.0+ 依赖Jakarta EE 9+(使用jakarta.servlet包),但Tomcat 9.0仅支持Jakarta EE 8(对应javax.servlet包),版本不匹配会导致DispatcherServlet无法被Tomcat正确初始化。

解决方法:

  • 降级Spring版本到5.3.x系列(兼容Tomcat 9和javax.servlet),或者
  • 升级Tomcat到10.0+版本(支持Jakarta EE 9+)

2. 编译版本与Spring版本不兼容

Spring 6.0要求Java版本至少为17,但你的pom.xml中指定了source和target为1.8,这会导致类加载异常,进而影响DispatcherServlet初始化。

解决方法:
如果选择保留Spring 6.0,修改maven-compiler-plugin的配置为Java 17+:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.10.1</version>
    <configuration>
        <source>17</source>
        <target>17</target>
    </configuration>
</plugin>

同时确保你的开发环境(JDK)版本为17+。

3. 验证DispatcherServlet初始化日志级别

确保日志级别设置为INFO,否则Initializing Spring DispatcherServlet日志可能不会显示。可以在项目中添加logback或log4j配置,将org.springframework.web的日志级别设为INFO。

4. 检查项目部署结构

确认打包后的war包中包含所有必要的class文件:

  • WEB-INF/classes下应有it.fogliafabrizio.corso.web和it.fogliafabrizio.corso.web.controller包的class文件
  • WEB-INF/lib下包含所有依赖的jar包

5. 替换AppInitializer的实现(可选)

如果上述方法无效,可以尝试使用WebApplicationInitializer接口直接实现,替代AbstractAnnotationConfigDispatcherServletInitializer:

package it.fogliafabrizio.corso.web;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletRegistration;

public class AppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) {
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.register(WebConfig.class);
        
        DispatcherServlet dispatcherServlet = new DispatcherServlet(context);
        dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
        
        ServletRegistration.Dynamic registration = servletContext.addServlet("dispatcher", dispatcherServlet);
        registration.setLoadOnStartup(1);
        registration.addMapping("/");
    }
}

内容的提问来源于stack exchange,提问作者Fabrizio Foglia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 21:25:22