Spring Boot Rest:使用@ControllerAdvice时保留默认异常处理器
Got it, let's break down why your default exception handler isn't working and fix this without overriding Spring's default handlers.
问题根源
When you extend ResponseEntityExceptionHandler, this class already provides built-in handlers for a bunch of Spring MVC standard exceptions (like MethodArgumentNotValidException, HttpMessageNotReadableException, etc.). These built-in handlers have higher priority than your @ExceptionHandler(Exception.class) method, so other exceptions are being handled by the parent class instead of your custom default handler. And as you noticed, some of those parent class handlers return status codes without a response body.
最佳解决方案:移除对ResponseEntityExceptionHandler的继承
The simplest and cleanest fix is to stop extending ResponseEntityExceptionHandler. This way:
- Your custom
@ExceptionHandler(PersonNotFoundException.class)will still catch your specific custom exception and return your desired response. - Spring's default exception handling mechanism will take care of all standard MVC exceptions, returning appropriate response bodies and status codes as it normally does.
- You can still add targeted handlers for other specific exceptions if needed, instead of using a broad
Exception.classcatch-all that forces the same status code for everything.
Here's the revised code:
@ControllerAdvice public class CustomGlobalExceptionHandler { // Handle your custom PersonNotFoundException @ExceptionHandler(PersonNotFoundException.class) public ResponseEntity<ErrorResponse> handlePersonNotFound(PersonNotFoundException ex) { ErrorResponse error = new ErrorResponse(HttpStatus.BAD_REQUEST.value(), "Invalid person Id"); return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST); } // Optional: Add handlers for other specific exceptions if you want custom responses @ExceptionHandler(NullPointerException.class) public ResponseEntity<ErrorResponse> handleNullPointer(NullPointerException ex) { ex.printStackTrace(); ErrorResponse error = new ErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Unexpected null reference error"); return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR); } // Generic error response class to standardize your responses public static class ErrorResponse { private int statusCode; private String message; public ErrorResponse(int statusCode, String message) { this.statusCode = statusCode; this.message = message; } // Getters and setters for serialization public int getStatusCode() { return statusCode; } public void setStatusCode(int statusCode) { this.statusCode = statusCode; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } }
为什么这个方案有效
- By not extending
ResponseEntityExceptionHandler, you're not overriding or interfering with Spring's default exception handling pipeline. - Your custom exception handlers only kick in for the exceptions you explicitly target, leaving all other exceptions to be handled by Spring's default logic (which includes proper response bodies for standard errors like 400, 404, etc.).
- Using
ResponseEntity<ErrorResponse>instead ofresponse.sendError()lets you return a structured, consistent response body for your custom exceptions, which aligns with your goal of a generic response format.
额外提示
If you ever need to customize how Spring handles a specific standard exception (like changing the response body for 404s), you can just add a dedicated @ExceptionHandler for that exact exception type, instead of using a broad catch-all or overriding the entire parent class logic.
内容的提问来源于stack exchange,提问作者Wildfire

