1. Обзор
В этом руководстве мы собираемся показать, как настроить Spring WebClient
— реактивный HTTP-клиент — для регистрации запросов и ответов.
2. Веб-клиент
WebClient
— реактивный и неблокирующий интерфейс для HTTP-запросов, основанный на Spring WebFlux . Он имеет функциональный, гибкий API с реактивными типами для декларативной композиции.
За кулисами WebClient
вызывает HTTP-клиент. Reactor Netty используется по умолчанию , также поддерживается реактивный HttpClient Jetty.
Кроме того, можно подключить другие реализации HTTP-клиента, настроив ClientConnector
для WebClient
.
3. Регистрация запросов и ответов
HttpClient
по
умолчанию , используемый WebClient
, является реализацией Netty, поэтому после
того, как мы изменим уровень ведения журнала реактора
`` . Веб-клиент#фильтры
: [
](/lessons/b/-spring-webclient-filters)
WebClient
.builder()
.filters(exchangeFilterFunctions -> {
exchangeFilterFunctions.add(logRequest());
exchangeFilterFunctions.add(logResponse());
})
.build()
В этом фрагменте кода мы добавили два отдельных фильтра для регистрации запроса и ответа.
Давайте реализуем logRequest
с помощью ExchangeFilterFunction#ofRequestProcessor
:
ExchangeFilterFunction logRequest() {
return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
if (log.isDebugEnabled()) {
StringBuilder sb = new StringBuilder("Request: \n");
//append clientRequest method and url
clientRequest
.headers()
.forEach((name, values) -> values.forEach(value -> /* append header key/value */));
log.debug(sb.toString());
}
return Mono.just(clientRequest);
});
}
logResponse
— то же самое, **но вместо этого мы должны использовать ExchangeFilterFunction#ofResponseProcessor
.
**
Теперь мы можем изменить уровень
журнала реактора.netty.http.client на INFO
или ERROR
, чтобы получить более чистый вывод.
4. Регистрация запроса и ответа с телом
HTTP-клиенты имеют функции для регистрации тела запросов и ответов. Таким образом, для достижения цели мы собираемся использовать HTTP-клиент с поддержкой журнала с нашим WebClient.
Мы можем сделать это, вручную установив WebClient.Builder#
clientConnector —
давайте посмотрим на HTTP-клиенты Jetty и Netty.
4.1. Ведение журнала с помощью Jetty HttpClient
Во-первых, давайте добавим зависимость Maven для jetty-reactive-httpclient
в наш pom:
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-reactive-httpclient</artifactId>
<version>1.1.6</version>
</dependency>
Затем мы собираемся создать собственный Jetty HttpClient
:
SslContextFactory.Client sslContextFactory = new SslContextFactory.Client();
HttpClient httpClient = new HttpClient(sslContextFactory) {
@Override
public Request newRequest(URI uri) {
Request request = super.newRequest(uri);
return enhance(request);
}
};
Здесь мы переопределили HttpClient#newRequest
, а затем обернули запрос
в средство расширения журнала.
Затем нам нужно зарегистрировать события с запросом, чтобы мы могли регистрировать, когда каждая часть запроса становится доступной:
Request enhance(Request request) {
StringBuilder group = new StringBuilder();
request.onRequestBegin(theRequest -> {
// append request url and method to group
});
request.onRequestHeaders(theRequest -> {
for (HttpField header : theRequest.getHeaders()) {
// append request headers to group
}
});
request.onRequestContent((theRequest, content) -> {
// append content to group
});
request.onRequestSuccess(theRequest -> {
log.debug(group.toString());
group.delete(0, group.length());
});
group.append("\n");
request.onResponseBegin(theResponse -> {
// append response status to group
});
request.onResponseHeaders(theResponse -> {
for (HttpField header : theResponse.getHeaders()) {
// append response headers to group
}
});
request.onResponseContent((theResponse, content) -> {
// append content to group
});
request.onResponseSuccess(theResponse -> {
log.debug(group.toString());
});
return request;
}
Наконец, нам нужно создать экземпляр WebClient :
WebClient
.builder()
.clientConnector(new JettyClientHttpConnector(httpClient))
.build()
Конечно, как и раньше, нам нужно установить уровень журнала RequestLogEnhancer
на DEBUG
.
4.2. Ведение журнала с помощью Netty HttpClient
Во-первых, давайте создадим Netty HttpClient
:
HttpClient httpClient = HttpClient
.create()
.wiretap(true)
После включения прослушки каждый запрос и ответ будут протоколироваться во всех подробностях.
Затем мы должны установить уровень журнала клиентского пакета Netty Reactor.netty.http.client
на DEBUG
:
logging.level.reactor.netty.http.client=DEBUG
Теперь давайте создадим WebClient
:
WebClient
.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.build()
Наш веб- клиент
будет подробно регистрировать каждый запрос и ответ, но формат встроенного регистратора Netty по умолчанию содержит как шестнадцатеричное, так и текстовое представление тел, а также множество данных о событиях запросов и ответов.
Итак, если нам нужен только текстовый регистратор для Netty, мы можем настроить HttpClient
:
HttpClient httpClient = HttpClient
.create()
.wiretap("reactor.netty.http.client.HttpClient",
LogLevel.DEBUG, AdvancedByteBufFormat.TEXTUAL);
5. Вывод
В этом руководстве мы использовали несколько методов регистрации данных запросов и ответов при использовании Spring WebClient
.
Как всегда, код доступен на GitHub .