Spring boot Rest отвечает пустым телом за исключения, кроме переопределенных в моем @ControllerAdvice - PullRequest
2 голосов
/ 10 июня 2019

У меня есть @ControllerAdvice, расширяющий ResponseEntityExceptionHandler, как попытку для меня контролировать стандартный ответ для любого исключения, вызванного в рабочем процессе вызова API.

Без консультации с Контролером. Я получаю общий ответ на основе HTML, сгенерированный Spring с правильными заголовками ответа. Но когда я добавляю свой @ControllerAdvice, 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, описывающей ошибку. Но в случае любого другого исключения, такого как HttpMediaTypeNotAcceptableException, весна отвечает пустым телом.

До того, как я добавил свой совет, Spring отвечал общим ответом об ошибке. Я новичок в весенней загрузке экосистемы. Нужна помощь в понимании, является ли это ожидаемым поведением, если существует лучший подход для достижения централизованной обработки ошибок.

Ответы [ 2 ]

0 голосов
/ 10 июня 2019

Это ожидаемое поведение. Взгляните на исходный код класса ResponseEntityExceptionHandler.

@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)

Если вам нужно по-разному обрабатывать определенные исключения, переопределите их, например, где я хотел отправить пользовательский ответ для HttpMessageNotReadableException

 @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);
    }
0 голосов
/ 10 июня 2019

Вам необходимо определить общую структуру исключений после использования @ 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());
}
...