error-page 的 location 必须是以 / 开头、相对于 web 应用根目录的路径,如 /errors/404.html;不支持 ../、协议前缀、el 表达式或 spring 视图解析,且文件需真实存在于部署后的 webapp 目录下。

error-page 的 location 必须是应用根路径下的相对路径
Web 容器(如 Tomcat)在解析 error-page 时,只接受以 / 开头、相对于 Web 应用根目录(即 webapp/ 目录)的路径。它不是文件系统路径,也不是类路径,更不支持 ../ 向上跳转或协议前缀。
-
location值必须以/开头,比如/errors/404.html,不能写成errors/404.html或./errors/404.html - 路径指向的是部署后实际可被 HTTP 访问的资源,所以要确保该文件真的放在
webapp/errors/404.html下,而不是src/main/webapp/下却忘了打包进去 - 不支持 JSP EL、
${}占位符,也不能用 Spring 的视图解析器逻辑——这是 Servlet 规范层的纯静态转发 - 如果用的是 WAR 包部署,路径区分大小写,
/Errors/404.html和/errors/404.html是两个不同资源
404 错误页面无法触发?检查是否被 Filter 或 Spring MVC 拦截了
常见现象:配置了 <error-page><error-code>404</error-code><location>/404.html</location></error-page>,但输入不存在路径时仍看到默认容器 404 页面,或跳到了 Spring 的 Whitelabel Error Page。
- Spring Boot 默认启用了
ErrorMvcAutoConfiguration,会接管所有错误响应,导致web.xml的error-page失效 - 普通 Spring MVC 项目中,如果
DispatcherServlet的<url-pattern>/</url-pattern>覆盖了全部请求,而 404 实际发生在静态资源未命中时,部分容器(如旧版 Tomcat)可能不会触发error-page,除非显式配置default-servlet-handler - 自定义
Filter如果没调用chain.doFilter()或吞掉了异常,也会中断错误传播链,让容器收不到原始错误信号
HTTP 状态码 vs 异常类:别混淆 error-code 和 exception-type
web.xml 中 error-page 支持两种匹配方式,行为和触发时机完全不同,混用会导致预期外的页面展示。
-
<error-code>500</error-code>匹配的是响应已提交的状态码,比如 servlet 主动调用response.sendError(500),或容器在处理请求时抛出未捕获异常后自动设的码 -
<exception-type>java.lang.NullPointerException</exception-type>匹配的是未被捕获的 Java 异常类型,但前提是该异常**未被任何 filter 或 servlet catch 处理掉**,且容器能识别其类型 - 同一个异常(如
NullPointerException)可能最终返回 500,但如果你只配了error-code,没配exception-type,就可能错过按异常类型定制页面的机会 - 注意:
exception-type不支持通配符或父类向上匹配(比如配了RuntimeException,不一定能捕获所有子类,取决于容器实现)
Tomcat 9+ 对 location 的额外限制:禁止访问 WEB-INF 和 META-INF
即使你在 location 里写了 /WEB-INF/jsp/error.jsp,Tomcat 9 及以后版本会直接拒绝并返回 404,这是安全加固措施,不是配置写错了。
- 所有以
/WEB-INF/或/META-INF/开头的location值都会被容器静默拦截,日志里可能只有类似 “Invalid error page location”的警告,没有明显报错 - 解决办法:把 JSP 或 HTML 文件移到
webapp/直接子目录下,比如/jsp/error.jsp,再在location中写对应路径 - 如果必须用 WEB-INF 下的资源,只能改用程序内跳转(如 filter 中判断 status 后
request.getRequestDispatcher("/WEB-INF/jsp/error.jsp").forward()),但这绕过了error-page机制
web.xml,却忘了它默认不生效。










