Spring Boot 中 404 默认由 DispatcherServlet 直接响应,不抛异常,故 @ControllerAdvice 无法捕获;推荐实现 ErrorController 接口统一处理,或配置 ErrorPageRegistrar 映射 /error/404,同时关闭 whitelabel 错误页。

Spring Boot 中 404(NOT_FOUND)默认由 Spring MVC 的 DispatcherServlet 处理,不抛出标准异常,而是直接返回 404 响应。因此不能靠 @ControllerAdvice 捕获 NotFoundException——因为根本没抛异常。要全局统一处理 404,需借助错误页面机制或自定义错误响应逻辑。
使用 ErrorController 自定义 404 响应
这是最直接、推荐的方式:实现 ErrorController 接口,接管所有错误路径(包括 /error)的处理。
- 创建一个类实现
org.springframework.boot.web.servlet.error.ErrorController - 重写
getErrorPath()返回"/error"(Spring Boot 默认错误端点) - 添加
@RequestMapping("/error")方法,在其中判断状态码是否为 404,并返回统一 JSON 或视图 - 确保该类被 Spring 扫描到(如放在主启动类同包或显式
@Component)
示例:
@RestController
public class GlobalErrorController implements ErrorController {
private final ErrorAttributes errorAttributes;
<pre class="brush:php;toolbar:false;">public GlobalErrorController(ErrorAttributes errorAttributes) {
this.errorAttributes = errorAttributes;
}
@RequestMapping("/error")
public ResponseEntity<map object>> handleError(HttpServletRequest request) {
HttpStatus status = (HttpStatus) request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
if (status == HttpStatus.NOT_FOUND) {
Map<string object> body = new HashMap();
body.put("code", 404);
body.put("message", "请求的资源不存在");
body.put("path", request.getRequestURI());
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(body);
}
// 其他错误可继续判断或委托默认逻辑
return ResponseEntity.status(status).body(errorAttributes.getErrorAttributes(
new ServletWebRequest(request), false));
}
@Override
public String getErrorPath() {
return "/error";
}</string></map>}
配置 ErrorPageRegistrar(适用于嵌入式 Servlet 容器)
如果使用 Tomcat/Jetty 等内嵌容器,可通过 ErrorPageRegistrar 将 404 映射到自定义控制器,适合需要区分页面与 API 场景。
- 实现
ErrorPageRegistrar,注册ErrorPage(HttpStatus.NOT_FOUND, "/error/404") - 再写一个
@Controller处理/error/404路径,返回 JSON 或跳转页面 - 注意:该方式对 WebFlux 不适用,仅限基于 Servlet 的应用
配合配置文件关闭 Whitelabel 错误页
避免默认白页干扰自定义逻辑,需在 application.yml 中关闭:
server:
error:
whitelabel:
enabled: false
同时可选配:
-
server.error.include-message: never(不暴露异常消息) -
server.error.include-binding-errors: never(不包含校验错误细节) -
spring.mvc.throw-exception-if-no-handler-found: true(让无匹配 handler 时抛出NoHandlerFoundException)
⚠️ 注意:throw-exception-if-no-handler-found 需搭配 spring.mvc.static-path-pattern 和静态资源路径配置,否则可能影响 CSS/JS 加载。
补充:捕获 NoHandlerFoundException(进阶用法)
开启 spring.mvc.throw-exception-if-no-handler-found=true 后,404 请求会抛出 NoHandlerFoundException,此时可用 @ControllerAdvice 捕获:
@ControllerAdvice
public class GlobalExceptionHandler {
<pre class="brush:php;toolbar:false;">@ExceptionHandler(NoHandlerFoundException.class)
public ResponseEntity<map object>> handle404(NoHandlerFoundException e, HttpServletRequest request) {
Map<string object> res = Map.of(
"code", 404,
"message", "接口不存在",
"path", request.getRequestURI()
);
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(res);
}</string></map>}
但该方式对静态资源 404 无效(如 /static/xxx.js 不存在),仍走容器默认逻辑;且需确保静态资源配置未覆盖该行为。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











