You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用@ControllerAdvice和@ExceptionHandler处理Spring 404异常?

解决Spring中404资源不存在返回自定义JSON的问题

为什么默认404没被你的@ExceptionHandler捕获?

当访问不存在的端点时,Spring的DispatcherServlet找不到对应的处理器(Handler),默认不会抛出异常,而是直接返回白标错误页,所以你的@RestControllerAdvice里的异常处理逻辑根本没触发。

方案一:开启NoHandlerFoundException并捕获

1. 添加配置

在application.properties中添加以下配置:

# 让DispatcherServlet在找不到处理器时抛出异常
spring.mvc.throw-exception-if-no-handler-found=true
# 关闭静态资源映射(如果你的项目不需要静态资源访问,否则静态资源不存在也会触发404异常)
spring.web.resources.add-mappings=false

如果用application.yml则是:

spring:
  mvc:
    throw-exception-if-no-handler-found: true
  web:
    resources:
      add-mappings: false

2. 在@RestControllerAdvice类中添加异常处理方法

先定义一个自定义的错误响应类(示例):

@Data
public class ErrorResponse {
    private int code;
    private String message;
    private long timestamp;

    public ErrorResponse(int code, String message) {
        this.code = code;
        this.message = message;
        this.timestamp = System.currentTimeMillis();
    }
}

然后在你的全局异常处理类中添加:

@RestControllerAdvice
public class GlobalExceptionHandler {

    // 处理请求方法不支持的异常(你已有的逻辑)
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public ResponseEntity<ErrorResponse> handleMethodNotSupported(HttpRequestMethodNotSupportedException e) {
        ErrorResponse response = new ErrorResponse(HttpStatus.METHOD_NOT_ALLOWED.value(), "请求方法不支持:" + e.getMethod());
        return new ResponseEntity<>(response, HttpStatus.METHOD_NOT_ALLOWED);
    }

    // 处理404资源不存在异常
    @ExceptionHandler(NoHandlerFoundException.class)
    public ResponseEntity<ErrorResponse> handleNotFound(NoHandlerFoundException e) {
        ErrorResponse response = new ErrorResponse(HttpStatus.NOT_FOUND.value(), "请求的资源不存在:" + e.getRequestURL());
        return new ResponseEntity<>(response, HttpStatus.NOT_FOUND);
    }
}

方案二:实现ErrorController接管所有错误

如果不想修改配置,也可以直接实现Spring的ErrorController接口,统一处理所有错误状态码,包括404:

@RestController
public class CustomErrorController implements ErrorController {

    @RequestMapping("/error")
    public ResponseEntity<ErrorResponse> handleError(HttpServletRequest request) {
        Integer statusCode = (Integer) request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
        String message = "请求出错";
        if (statusCode != null) {
            if (statusCode == HttpStatus.NOT_FOUND.value()) {
                message = "请求的资源不存在";
            } else if (statusCode == HttpStatus.METHOD_NOT_ALLOWED.value()) {
                message = "请求方法不支持";
            }
            // 可以添加更多状态码的处理逻辑
        }
        ErrorResponse response = new ErrorResponse(statusCode != null ? statusCode : HttpStatus.INTERNAL_SERVER_ERROR.value(), message);
        return new ResponseEntity<>(response, HttpStatus.valueOf(statusCode != null ? statusCode : HttpStatus.INTERNAL_SERVER_ERROR.value()));
    }

    // Spring Boot 2.3+ 不需要重写getErrorPath(),因为默认就是"/error"
}

两种方案对比

  • 方案一:精准针对404异常,只处理找不到处理器的情况,适合只需要定制404响应的场景。
  • 方案二:统一处理所有错误状态码(如500、403等),适合需要全局统一错误响应格式的场景。

内容的提问来源于stack exchange,提问作者hc0re

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 20:35:16