spring mvc 默认不将404视为异常,需启用throw-exception-if-no-handler-found并配置静态资源路径隔离,使nohandlerfoundexception被@restcontrolleradvice捕获返回json;405同理需额外启用throw-exception-if-no-handler-found-for-method。

Spring MVC 默认不把 404 当作“异常”来处理,而是由 DispatcherServlet 直接返回 HTTP 404 响应(比如 Whitelabel 页面),所以它不会进入 @ExceptionHandler 流程。要让它被统一捕获并返回 JSON,关键不是“拦截 404”,而是**让 Spring 主动抛出 NoHandlerFoundException,再用全局异常处理器接住**。
启用 NoHandlerFoundException 抛出
这是前提。Spring Boot 默认静默处理未匹配路径,需显式开启异常抛出:
- 在
application.yml中添加:
mvc:
throw-exception-if-no-handler-found: true
⚠️ 单独配这一项通常无效——因为 Spring Boot 默认把 /error 路径也当作静态资源处理,导致请求仍被 BasicErrorController 拦截,根本不会触发该异常。
隔离静态资源路径
必须配合调整静态资源映射,避免 /error 被静态处理器“抢走”:
- 推荐方式:限定静态资源只匹配特定前缀,例如:
web:
resources:
add-mappings: true
mvc:
static-path-pattern: /static/**
throw-exception-if-no-handler-found: true
这样,像 /api/user/123 这类非 /static/** 开头的请求,若无对应 Controller,就会真正抛出 NoHandlerFoundException。
- 替代方式(更彻底):禁用默认静态资源映射(适用于纯 API 服务):
web:
resources:
add-mappings: false
在 @RestControllerAdvice 中捕获
配置生效后,NoHandlerFoundException 就能被全局异常处理器捕获:
- 定义一个
@RestControllerAdvice类,添加对应方法:
public class GlobalExceptionHandler {
@ExceptionHandler(NoHandlerFoundException.class)
public Result> handle404(NoHandlerFoundException e) {
return Result.fail("404", "请求地址不存在");
}
}
其中 Result 是你项目里统一的响应封装类(含 code、msg、data 字段),确保返回的是标准 JSON,而非 HTML 页面。
注意 405 方法不支持的情况
同理,405(Method Not Allowed)也需要额外配置才能被捕获:
- 在相同配置基础上,加一行:
mvc:
throw-exception-if-no-handler-found: true
# 同时启用 405 异常抛出
throw-exception-if-no-handler-found-for-method: true
然后在异常处理器中补充:
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)public Result> handle405(HttpRequestMethodNotSupportedException e) {
return Result.fail("405", "不支持的请求方法: " + e.getMethod());
}











