스프링 부트 내 @ControllerAdvise에서 재정의된 예외 이외의 예외에 대해 빈 본문으로 응답하는 Rest
ResponseEntity를 확장하는 @ControllerAdvise가 있습니다.API 호출 워크플로우 내에서 제기된 예외에 대한 표준 응답을 제어하기 위한 시도로 ExceptionHandler를 사용합니다.
컨트롤러의 조언 없이.올바른 응답 헤더로 봄에 생성된 HTML 기반의 일반 응답을 받습니다.그러나 @ControllerAdvisory를 추가해도 Spring은 일반 오류 본문으로 응답하지 않습니다.본문이 비어 있고 올바른 응답 헤더가 있습니다.
@Override
protected ResponseEntity<Object> handleMissingServletRequestParameter(MissingServletRequestParameterException ex,
HttpHeaders headers, HttpStatus status, WebRequest request) {
String erroMessage = "Required Parameter: '"+ex.getParameterName()+"' was not available in the request.";
TrsApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, erroMessage, ex, ApiErrorCode.INVALID_REQUEST);
return buildResponseEntity(apiError);
}
이제 요청에 필요한 매개 변수가 누락된 경우, 흐름은 재정의된 구현을 올바르게 트리거하고 오류를 설명하는 JSON 페이로드로 응답합니다.그러나 HttpMediaTypeNotAcceptable과 같은 다른 예외의 경우예외적으로 봄은 빈 몸으로 응답합니다.
제가 조언을 덧붙이기 전에 봄은 일반적인 오류 대응으로 대응하고 있었습니다.저는 봄부츠 생태계가 처음입니다.중앙 집중식 오류 처리에 대한 더 나은 접근 방식이 있는지 예상되는 동작인지 이해하는 데 도움이 필요합니다.
ControllerAdvices 클래스가 확장될 때 삼킨 몸에 대한 해결책을 찾은 것 같습니다.ResponeEntityExceptionHandler
이 경우 설정은 다음과 같습니다.
@ControllerAdvice
@Slf4j
class GlobalExceptionHandlers extends ResponseEntityExceptionHandler {
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(
MethodArgumentNotValidException exception,
HttpHeaders headers,
HttpStatus status,
WebRequest request) {
// logic that creates apiError object (object with status, message, errorCode, etc)
//...
return handleExceptionInternal(exception, apiError, headers, status, request);
}
그리고 이것은 수업의 예외를 위한 매력처럼 작용했습니다.MethodArgumentNotValidException
하지만 다른 모든 예외를 어겼습니다ResponseEntityExceptionHandler
그리고 그들을 위해 빈 응답 본문을 반환했습니다.
하지만 해결책은 간단합니다. 그냥 덮어씁니다.handleExceptionInternal
부터ResponseEntityExceptionHandler
:
@ControllerAdvice
@Slf4j
class GlobalExceptionHandlers extends ResponseEntityExceptionHandler {
/// ... code from previous snippet
@Override
protected ResponseEntity<Object> handleExceptionInternal(
Exception exception,
Object body,
HttpHeaders headers,
HttpStatus status,
WebRequest request) {
// for all exceptions that are not overriden, the body is null, so we can
// just provide new body based on error message and call super method
var apiError = Objects.isNull(body)
? new ApiError(status, exception.getMessage()) // <--
: body;
return super.handleExceptionInternal(exception, apiError, headers, status, request);
}
}
이것은 예상된 동작입니다.클래스 ResponseEntity의 소스 코드를 확인합니다.예외 처리기.
@ExceptionHandler({
org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException.class,
HttpRequestMethodNotSupportedException.class,
HttpMediaTypeNotSupportedException.class,
HttpMediaTypeNotAcceptableException.class,
MissingPathVariableException.class,
MissingServletRequestParameterException.class,
ServletRequestBindingException.class,
ConversionNotSupportedException.class,
TypeMismatchException.class,
HttpMessageNotReadableException.class,
HttpMessageNotWritableException.class,
MethodArgumentNotValidException.class,
MissingServletRequestPartException.class,
BindException.class,
NoHandlerFoundException.class,
AsyncRequestTimeoutException.class
})
public final ResponseEntity<Object> handleException(Exception ex, WebRequest request) {
이러한 모든 예외는 응답 본문 없이 처리됩니다.일반적인 메서드가 호출됩니다.
//second parameter is body which is null
handleExceptionInternal(ex, null, headers, status, request)
특정 예외를 다르게 처리해야 하는 경우, HttpMessageNotReadable에 대한 사용자 지정 응답을 보내려는 경우와 같이 예외를 재정의합니다.예외
@Override
protected ResponseEntity<Object> handleHttpMessageNotReadable(HttpMessageNotReadableException ex,
HttpHeaders headers, HttpStatus status, WebRequest request)
{
logger.error("handleHttpMessageNotReadable()", ex);
ValidationErrors validationErrors = null;
if (ex.getRootCause() instanceof InvalidFormatException) {
InvalidFormatException jacksonDataBindInvalidFormatException = (InvalidFormatException) ex.getRootCause();
validationErrors = new ValidationErrors(jacksonDataBindInvalidFormatException.getOriginalMessage());
}
headers.add("X-Validation-Failure", "Request validation failed !");
return handleExceptionInternal(ex, validationErrors, headers, status, request);
}
@ControllerAdvice를 사용한 후에는 일반 예외 구조를 정의해야 합니다.
@ResponseBody
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ErrorResponse generationExceptionHandler(Exception e){
log.info("Responding INTERNAL SERVER ERROR Exception");
return new ErrorResponse(ServiceException.getSystemError());
}
언급URL : https://stackoverflow.com/questions/56527952/spring-boot-rest-responding-with-empty-body-for-exceptions-other-than-the-ones-o
'programing' 카테고리의 다른 글
ALTER TABLE 구문 - DIRECTORY 키워드 누락 (0) | 2023.07.28 |
---|---|
pphp 도커 이미지에 pdo 드라이버를 설치하는 방법은 무엇입니까? (0) | 2023.07.28 |
테이블에 문 수준 트리거를 구현할 때 영향을 받는 모든 행에 대해 OLD 및 NEW 레코드를 가져올 수 있습니까? (0) | 2023.07.28 |
미국 달러 금액을 나타내기 위해 사용할 수 있는 가장 좋은 장고 모델 필드는 무엇입니까? (0) | 2023.07.28 |
TensorFlow에서 변수와 get_variable의 차이 (0) | 2023.07.23 |