如何用@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
相关产品推荐
相关产品推荐

