Spring MVC项目Tomcat部署访问返回404 Not Found如何修复
你的项目存在4个核心配置/结构错误,逐一修复即可正常访问:
问题1:Maven项目结构不符合WAR包规范
你当前webapp目录直接放在src根目录下,标准Maven WAR项目要求webapp必须位于src/main路径下,和java、resources目录平级,否则Maven打包时不会将webapp下的jsp、xml配置文件打入部署包,Tomcat自然找不到对应资源。
修正后的标准目录结构:
src - main - java - com - example - mvc - HomeController.java - resources - webapp - WEB-INF - view - main-menu.jsp - applicationContext.xml - web.xml
问题2:DispatcherServlet未加载Spring MVC配置
你在web.xml中仅通过ContextLoaderListener给Spring根上下文指定了applicationContext.xml路径,但DispatcherServlet默认会加载WEB-INF/[servlet-name]-servlet.xml路径下的配置(你的servlet名为DispatcherServlet,默认找DispatcherServlet-servlet.xml),导致你写的组件扫描、视图解析器、MVC注解驱动配置全部没有生效,请求找不到对应的Controller映射。
修正方式:给DispatcherServlet添加初始化参数,显式指定配置文件路径,修改后的web.xml servlet配置如下:
<servlet> <servlet-name>DispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 新增:指定MVC配置文件位置 --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <!-- 简单项目可以直接删掉下面的根上下文配置,不需要拆分父子容器,减少配置复杂度 <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> --> <servlet-mapping> <servlet-name>DispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
问题3:Spring配置文件命名空间绑定错误
你的applicationContext.xml中把mvc前缀错误绑定到了cache命名空间地址,导致<mvc:annotation-driven>标签无法正常解析,注解驱动的请求映射不生效。同时配置里引入了大量没用的cocoon、avalon命名空间,容易引发配置冲突。
修正后的applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd "> <context:component-scan base-package="com.example.mvc"/> <mvc:annotation-driven/> <!-- 删除多余的BeanNameUrlHandlerMapping,annotation-driven已经自动注册了注解需要的处理器映射器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/view/"/> <property name="suffix" value=".jsp"/> </bean> </beans>
问题4:POM配置冗余+缺少WAR打包插件
你pom中引入的6.x版本Jetty插件是十几年前的旧版本,且你使用Tomcat部署,这个插件完全没用可以删掉。另外缺少maven-war-plugin,可能导致打包时资源遗漏。同时注意你引入的javax.servlet-api 4.0.1仅适配Tomcat 9版本,不要用Tomcat 10(Tomcat10改用jakarta包名,和Spring 5.x不兼容)。
修正后的build配置块:
<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> </plugins> </build>
如果JDK18启动Tomcat报错,可以把maven.compiler.source和target降到11,兼容性更好。
部署验证
在IDEA配置Tomcat部署时,确认部署的是项目的war:exploded产物,如果你设置的应用上下文路径是/,启动后访问http://localhost:8080/hello即可看到main-menu.jsp页面;如果上下文路径设置为/Demo,访问地址为http://localhost:8080/Demo/hello。
内容的提问来源于stack exchange,提问作者Quoc Hung

