Перейти к основному содержимому

Регистрация вызовов Spring WebClient

· 4 мин. чтения

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 .