1. Обзор
Часто полезно использовать код состояния из ответа HTTP, чтобы определить, что приложение должно делать дальше с данным ответом.
В этом руководстве мы рассмотрим, как получить доступ к коду состояния и тексту ответа, возвращаемому из запроса REST, с помощью WebClient WebFlux.
WebClient
был представлен в Spring 5 и может использоваться для асинхронного ввода-вывода при вызове служб RESTful.
2. Вариант использования
При выполнении вызовов RESTful к другим службам приложения обычно используют возвращенный код состояния для запуска различных функций. Типичные варианты использования включают изящную обработку ошибок, инициирование повторных попыток запроса и определение ошибки пользователя.
Таким образом, при совершении вызовов REST часто недостаточно просто получить код ответа. Иногда нам также нужно тело ответа.
В следующих примерах давайте посмотрим, как мы можем проанализировать тело ответа от клиента REST WebClient
. Мы свяжем наше поведение с возвращенным кодом состояния и будем использовать два метода извлечения кода состояния, предоставляемые WebClient
: onStatus
и ExchangeFilterFunction.
3. Использование onStatus
onStatus
— это встроенный механизм, который можно использовать для обработки ответа WebClient .
Это позволяет нам применять детализированную функциональность на основе конкретных ответов (таких как 400, 500, 503 и т. д.) или категорий статусов (таких как 4XX, 5XX и т. д.):
WebClient
.builder()
.build()
.post()
.uri("/some-resource")
.retrieve()
.onStatus(
HttpStatus.INTERNAL_SERVER_ERROR::equals,
response -> response.bodyToMono(String.class).map(Exception::new))
Метод onStatus
требует двух параметров. Первый — это предикат, который принимает код состояния. Выполнение второго параметра основано на выводе первого. Вторая — это функция, которая сопоставляет ответ с Mono
или Exception.
В этом случае, если мы увидим INTERNAL_SERVER_ERROR
(т. е. 500), мы возьмем тело с помощью bodyToMono,
а затем сопоставим его с новым Exception
.
Мы можем связать вызовы onStatus
, чтобы обеспечить функциональность для различных состояний:
Mono<String> response = WebClient
.builder()
.build()
.post()
.uri("some-resource")
.retrieve()
.onStatus(
HttpStatus.INTERNAL_SERVER_ERROR::equals,
response -> response.bodyToMono(String.class).map(CustomServerErrorException::new))
.onStatus(
HttpStatus.BAD_REQUEST::equals,
response -> response.bodyToMono(String.class).map(CustomBadRequestException::new))
...
.bodyToMono(String.class);
// do something with response
Теперь вызовы onStatus
сопоставляются с нашими пользовательскими исключениями. Мы определили типы исключений для каждого из двух статусов ошибок. Метод onStatus
позволяет нам использовать любой выбранный нами тип.
4. Использование функции ExchangeFilterFunction
ExchangeFilterFunction
— это еще один способ обработки определенных кодов состояния и получения тела ответа .
В отличие от onStatus
фильтр обмена является гибким и применяется к функциям фильтра на основе любого логического выражения.
Мы можем извлечь выгоду из гибкости функции ExchangeFilterFunction
для охвата тех же категорий, что и функция onStatus
.
Во-первых, мы определим метод для обработки возвращаемой логики на основе кода состояния, заданного ClientResponse
:
private static Mono<ClientResponse> exchangeFilterResponseProcessor(ClientResponse response) {
HttpStatus status = response.statusCode();
if (HttpStatus.INTERNAL_SERVER_ERROR.equals(status)) {
return response.bodyToMono(String.class)
.flatMap(body -> Mono.error(new CustomServerErrorException(body)));
}
if (HttpStatus.BAD_REQUEST.equals(status)) {
return response.bodyToMono(String.class)
.flatMap(body -> Mono.error(new CustomBadRequestException(body)));
}
return Mono.just(response);
}
Далее мы определим фильтр и используем ссылку на метод для нашего обработчика:
ExchangeFilterFunction errorResponseFilter = ExchangeFilterFunction
.ofResponseProcessor(WebClientStatusCodeHandler::exchangeFilterResponseProcessor);
Подобно вызовам onStatus
, мы сопоставляем наши типы исключений
при ошибке. Однако использование Mono.error
завершит это исключение
в ReactiveException.
Эту вложенность следует учитывать при обработке ошибки .
Теперь давайте применим это к экземпляру WebClient
, чтобы добиться того же эффекта, что и связанный вызов onStatus
:
Mono<String> response = WebClient
.builder()
.filter(errorResponseFilter)
.build()
.post()
.uri("some-resource")
.retrieve()
.bodyToMono(String.class);
// do something with response
5. Вывод
В этой статье мы рассмотрели несколько методов получения тела ответа на основе заголовка состояния HTTP .
Основываясь на коде состояния, метод onStatus
позволяет нам подключать определенные функции. Кроме того, мы можем использовать метод фильтра
, чтобы подключить метод общего назначения для обработки постобработки всех ответов.
Как всегда, весь код в этом руководстве можно найти на GitHub .