最好扩展 Spring 的 ResponseEntityExceptionHandler 类并以您想要的方式自定义它,例如:
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.lang.Nullable;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import javax.validation.ValidationException;
@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(ValidationException.class)
protected ResponseEntity<Object> handle(ValidationException ex) {
return new ResponseEntity<>(getError(HttpStatus.BAD_REQUEST, ex), new HttpHeaders(), HttpStatus.BAD_REQUEST);
}
@ExceptionHandler
protected ResponseEntity<Object> handle(Exception ex, WebRequest request) {
try {
return super.handleException(ex, request);
} catch (Exception e) {
return handleExceptionInternal(ex, null, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR, request);
}
}
@Override
protected ResponseEntity<Object> handleExceptionInternal(Exception ex, @Nullable Object body, HttpHeaders headers, HttpStatus status, WebRequest request) {
if (HttpStatus.Series.SERVER_ERROR == status.series()) {
log.error("Unexpected error.", ex);
}
return new ResponseEntity<>(getError(status, ex), headers, status);
}
private ApiError getError(HttpStatus status, Exception ex) {
return ApiError.builder()
.status(status.value())
.message(ex.getMessage())
.build();
}
}
这样您可以覆盖 Spring 的默认错误响应正文,声明您的自定义异常(例如 ValidationException)以及允许 Spring 处理其在 ResponseEntityExceptionHandler 中声明的默认异常。
请注意,尽管在 Spring 4.x 中不需要围绕 super.handleException(ex, request) 进行 try-catch,但由于底层 ResponseEntityExceptionHandler 实现的更改,在 Spring 5.x 中是必需的。