
通过配置 `spring.mvc.throw-exception-if-no-handler-found=true` 并调整静态资源路径,可使未匹配的请求触发 `@exceptionhandler`,从而实现 404 异常的全局 json 格式化响应。
在 Spring Boot 中,@ControllerAdvice(或其 REST 专用变体 @RestControllerAdvice)配合 @ExceptionHandler 是处理控制器层异常的标准方式。但默认情况下,404(Not Found)错误并不会进入 @ExceptionHandler 流程——因为该异常发生在 DispatcherServlet 的请求分发阶段(即“找不到任何 HandlerMapping 匹配该 URL”),而非控制器执行过程中抛出的异常。此时 Spring Boot 会直接返回 Whitelabel 错误页(HTML),而非调用你的全局异常处理器。
要让 404 也能被 @ExceptionHandler 捕获,关键在于 强制 Spring 在无处理器匹配时抛出 NoHandlerFoundException,而非静默返回 404 响应。这需要两个协同配置:
✅ 步骤一:启用异常抛出机制
在 application.yml(或 application.properties)中启用:
spring:
mvc:
throw-exception-if-no-handler-found: true⚠️ 注意:仅设置此项不够!Spring Boot 默认将静态资源路径设为 /**,而 Whitelabel 错误页本质上是静态资源(由 BasicErrorController 提供)。若不调整静态路径,throw-exception-if-no-handler-found 将被忽略(因为 /error 路径仍能被静态资源处理器匹配)。
✅ 步骤二:隔离静态资源路径
方案 A(推荐):显式限定静态资源路径,避免覆盖 /error:
spring:
mvc:
throw-exception-if-no-handler-found: true
static-path-pattern: /static/**这样,所有非 /static/** 开头的请求(如 /api/v1/itemss)若无对应 Controller,则触发 NoHandlerFoundException。
方案 B:禁用自动配置,手动接管 Web MVC(适用于需深度定制场景):
@Configuration
@EnableWebMvc // ⚠️ 关闭 Spring Boot 的 WebMvcAutoConfiguration
public class WebConfig implements WebMvcConfigurer {
// 可选:自定义资源处理器等
}再配合 spring.mvc.throw-exception-if-no-handler-found=true 即可生效。
✅ 步骤三:添加 404 异常处理器
在你的 @RestControllerAdvice 类中添加:
@ExceptionHandler(NoHandlerFoundException::class)
fun handleNoHandlerFound(
exception: NoHandlerFoundException,
request: HttpServletRequest
): ResponseEntity {
logger().warn("404 Not Found: {}", exception.requestURL)
val notFound = HttpStatus.NOT_FOUND
val apiError = ApiError(
requestURI = exception.requestURL,
status = notFound.value(),
statusText = notFound.reasonPhrase,
createdAt = OffsetDateTime.now(),
errorMessage = "Requested resource does not exist"
)
return ResponseEntity(apiError, notFound)
} ? 提示:NoHandlerFoundException 的 requestURL 字段需通过 exception.requestURL 获取(Kotlin 中注意空安全),或从 request.requestURL.toString() 提取。
✅ 最终效果
访问 GET /api/v1/itemss 将返回标准 JSON:
{
"requestUri": "/api/v1/itemss",
"status": 404,
"statusText": "Not Found",
"createdAt": "2023-01-12T16:52:06.932108+02:00",
"errorMessage": "Requested resource does not exist"
}⚠️ 注意事项
- 确保 NoHandlerFoundException 的包导入正确:org.springframework.web.servlet.NoHandlerFoundException;
- 若使用 Spring Security,请确认 /error 路径未被拦截(通常需放行);
- @EnableWebMvc 会完全关闭 Spring Boot 的 Web 自动配置,仅在必要时选用;
- 生产环境建议结合 ErrorAttributes 或 ErrorController 做更健壮的错误溯源。
通过以上三步配置,即可将 404 纳入统一的 JSON 异常处理体系,保持 API 响应风格一致,提升客户端集成体验与服务可观测性。










