Реализация интерфейса ResponseErrorHandler

Я пытаюсь переопределить интерфейс ResponseErrorHandler, чтобы иметь возможность вернуть весь запрос (код состояния, тело и т. д.) в случае любого ответа, отличного от 2xx.

Я заметил, что Spring (RestTemplate) по умолчанию возвращает исключение в случае ответа, отличного от 2xx. Я не хочу возвращать исключение, я просто хочу иметь возможность вернуть:

new ResponseEntity(HttpStatus.STATUS_CODE)

Следуя некоторым учебникам, я нашел следующий код:

@Component
public class LoginErrorHandler
        implements ResponseErrorHandler {

    @Override
    public boolean hasError(ClientHttpResponse httpResponse)
            throws IOException {

        return (
                httpResponse.getStatusCode().series() == CLIENT_ERROR
                        || httpResponse.getStatusCode().series() == SERVER_ERROR);
    }

    @Override
    public void handleError(ClientHttpResponse httpResponse)
            throws IOException {
        if (httpResponse.getStatusCode()
                .series() == SERVER_ERROR) {
            // handle SERVER_ERROR
        } else if (httpResponse.getStatusCode()
                .series() == CLIENT_ERROR) {
            // handle CLIENT_ERROR
        }
    }

(Ссылка)

Но я не понял, как я могу вернуть ResponseEntity без изменения возврата метода (чего я не могу реализовать, реализуя метод).

Реализация:

HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new LoginErrorHandler());

return restTemplate.postForEntity(url, request, String.class);
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
2 530
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы можете использовать аннотации Spring ControllerAdvice и ExceptionHandler для обработки исключений в вашем приложении. Код ниже возвращает код состояния 500 http, если в вашем запросе встречается какое-либо исключение. Вы можете добавить другие классы исключений или свой собственный пользовательский класс для обработки определенных случаев и возврата определенных кодов состояния клиенту.

Редактировать

Обработка каждого кода не будет хорошей идеей. Скорее вы можете обернуть их в свое собственное исключение и предоставить правильное сообщение своей клиентской службе. Тем не менее вы можете попробовать что-то вроде ниже.

@Component
@ControllerAdvice
public class MyExceptionHandler {

    @ExceptionHandler(HttpClientErrorException.BadRequest.class)
    @ResponseStatus(code=HttpStatus.BAD_REQUEST, reason = "Bad Request", value=HttpStatus.BAD_REQUEST)
    public void handleBadRequest(HttpClientErrorException.BadRequest e) {

        //handle bad request exception
    }

    @ExceptionHandler(HttpClientErrorException.NotFound.class)
    @ResponseStatus(code=HttpStatus.NOT_FOUND, reason = "Not Found", value=HttpStatus.NOT_FOUND)
    public void handleNotFound(HttpClientErrorException.NotFound e) {

        //handle Not Found
    }

    @ExceptionHandler(HttpServerErrorException.InternalServerError.class)
    @ResponseStatus(code=HttpStatus.INTERNAL_SERVER_ERROR, reason = "Internal Server Error", value=HttpStatus.INTERNAL_SERVER_ERROR)
    public void handleInternalServerError(HttpServerErrorException.InternalServerError e) {

        //handle internal server error
    }

//more methods for each code.
}

Затем обработайте коды из вашего шаблона отдыха, как показано ниже. Здесь вы не сможете вернуть тело ответа клиенту.

@Component
public class LoginErrorHandler
        implements ResponseErrorHandler {

    @Override
    public boolean hasError(ClientHttpResponse httpResponse)
            throws IOException {

        return (httpResponse.getStatusCode() != HttpStatus.OK);
    }

    @Override
    public void handleError(ClientHttpResponse httpResponse)
            throws IOException {
        if (httpResponse.getRawStatusCode() >=400 && httpResponse.getRawStatusCode()<500 ) {
            throw HttpClientErrorException.create(httpResponse.getStatusCode(), httpResponse.getStatusText(), httpResponse.getHeaders(), null, null); 
        }else if (httpResponse.getRawStatusCode() >=500){
            throw HttpServerErrorException.create(httpResponse.getStatusCode(), httpResponse.getStatusText(), httpResponse.getHeaders(), null, null);
        }else {
            //throw some other exceptions for other codes and catch them in controller advice.
        }
    }
}

Привет, Нитин. Должен ли я добавить @ResponseStatus для каждого кода состояния в одном и том же методе? Или я должен использовать один метод для одного исключения? Кроме того, как мне использовать его в RestTemplate, если он не является подклассом ResponseErrorHandler?

FearX 18.06.2019 13:40

Вам нужно использовать другие методы для других исключений. Вы не можете вернуть несколько кодов состояния для одного и того же исключения.

Nitin Zadage 18.06.2019 13:42

Я понимаю. Должен ли я что-то делать с методами «hasError» и «handleError», которые исходят от ResponseErrorHandler?

FearX 18.06.2019 13:45

Поэтому мне не нужно использовать restTemplate.setErrorHandler(); ?

FearX 18.06.2019 15:44
Ответ принят как подходящий

Ты можешь это сделать:

@Component
@ControllerAdvice
public class LoginErrorHandler{

    @ExceptionHandler(HttpClientErrorException.class)
    @ResponseBody
    public void handleError(HttpClientErrorException e, HttpServletResponse response) throws IOException {
    response.sendError(e.getRawStatusCode(), e.getStatusText());
    }
}

Это вы генерируете весь код состояния, который должен отбрасывать исключение, и он возвращается в теле.

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

Исключение ResponseEntityExceptionHandler:, вызванное нашими методами конечной точки (методы, аннотированные @RequestMapping)

A convenient base class for @ControllerAdvice classes that wish to provide centralized exception handling across all @RequestMapping methods through @ExceptionHandler methods.

ResponseErrorHandler: Spring предоставляет хук ResponseErrorHandler, который можно реализовать для обработки исключений, создаваемых внешними службами. Для вызова любой внешней службы, скорее всего, вы будете использовать RestTemplate. RestTemplate может генерировать три типа исключений, перечисленных ниже:

HttpClientErrorException : For 4xx series status codes or Client errors.
HttpServerErrorException : For 5xx series status codes or server errors
RestClientException : Any other status codes like 3xx series

Для упрощения мы можем обрабатывать эти исключения как блок catch отдельно, но это приведет к тому, что в нашем сервисе будет разбросано много шаблонного кода. Интерфейс стратегии, используемый RestTemplate, чтобы определить, есть ли ошибка в конкретном ответе.

Есть два шага к использованию ResponseErrorHandler:

Шаг 1. Создайте собственный класс обработчика ошибок, реализуя ResponseErrorHandler и реализуя его методы hasError и handleError

Шаг 2: Нам нужно внедрить реализацию ResponseErrorHandler в экземпляр RestTemplate следующим образом: По умолчанию в RestTemplate errorHandler указывает на DefaultResponseErrorHandler.

Источник

Другие вопросы по теме