Spring Boot 通过 resources/static/error/ 目录接管 404 和 500 页面,需放纯数字命名的 HTML 或模板文件;仅对 DispatcherServlet 内异常生效,异步、Filter 或容器层错误需额外处理;自定义 ErrorController 需实现接口并关闭白标页;Nginx 和 CDN 需单独配置兜底错误页。
Spring Boot 里怎么接管 500 和 404 页面
直接用 resources/static/error/ 目录就行,spring boot 会自动扫描这个路径下的模板或静态文件。它按状态码匹配:放一个 404.html 就能捕获所有未找到资源的请求,500.html 同理。
注意两点:一是这个目录必须在 classpath 根路径下(即 src/main/resources/static/error/),二是文件名必须是纯数字(如 404.html、500.html),不能带下划线或后缀以外的字符。
-
error目录只对 Spring MVC 的请求生效,静态资源 404(比如直接访问不存在的 JS 文件)可能绕过它,得靠 WebServer 配置补漏 - 如果用了 Thymeleaf 或 Freemarker,可以放
404.html或404.ftl,模板引擎会自动渲染;纯静态 HTML 也能用,但拿不到异常信息 - 想在页面里显示错误详情(比如异常消息),得用模板引擎,并在模板中读取
${error}、${status}、${message}这些内置变量
为什么 500 页面有时不显示自定义内容
常见原因是异常没被 Spring MVC 拦截到——比如 Filter 抛异常、异步线程里出错、或者 Servlet 容器层(如 Tomcat)先处理了错误响应。
Spring Boot 默认只接管 DispatcherServlet 处理链内的异常。一旦异常跳出这个范围,就走容器默认逻辑,你的 error/500.html 就不会触发。
- 检查是否在
@ControllerAdvice或@ExceptionHandler中吞掉了异常但没返回视图,导致流程没进错误页面流程 - 异步方法(
@Async)抛异常默认不传播,需手动捕获并记录,否则用户看到的是空白页或连接重置 - Tomcat 等嵌入式容器有自己的
error-page配置,若在application.properties里写了server.error.whitelabel.enabled=false却没配好静态资源路径,可能 fallback 到容器默认页
ErrorController 接口和 BasicErrorController 怎么配合用
Spring Boot 内置的 BasicErrorController 是默认实现,它负责把错误转成视图或 JSON 响应。如果你要改行为(比如统一加日志、重定向到登录页、或根据 Accept 头返回不同格式),就得自己写个 ErrorController 实现。
自定义时别直接继承 BasicErrorController,而是实现 ErrorController 接口,并用 @RequestMapping("${server.error.path:${error.path:/error}}") 显式绑定路径。
- 返回
ModelAndView就走 HTML 流程,返回ResponseEntity可控制状态码和 body,适合 API 场景 - 别忘了在配置里关掉白标页:
server.error.whitelabel.enabled=false,否则自定义控制器可能被忽略 - 如果同时用了 Spring Security,确保
/error路径没被拦截,否则会跳 401 而不是显示你的 500 页面
Nginx 层要不要也配 error_page
要,但只作为兜底。Spring Boot 的错误页面只管应用内 HTTP 请求,而 Nginx 可能因超时、上游不可达、SSL 握手失败等场景直接返回错误,这些 Spring 根本收不到。
典型做法是在 Nginx 配置里加 error_page 500 502 503 504 /50x.html,并把 50x.html 放到 Nginx 的 html/ 目录下。注意路径别写错,且确保该文件可被 public 访问。
- 不要让 Nginx 的
error_page指向 Spring 应用里的/error/500.html,这会引发循环代理或权限问题 - 前后端分离项目里,前端路由 404(如 Vue Router 的 hash 模式)和后端 404 是两回事,Nginx 的
error_page 404应指向index.html,而非后端错误页 - 如果用了 CDN,CDN 自身也有错误响应机制,得确认它是否透传源站的 4xx/5xx 状态码,否则用户看到的是 CDN 缓存的旧错误页
真正麻烦的是多层代理下的错误传递:Nginx → Spring Cloud Gateway → 微服务,每一层都可能截断或重写错误响应,得逐层确认状态码和响应体是否透传到位。










