@Tobske второй линке из раздела> = 2.1.0 заботится о замаскированных заголовках, вам не нужно никаких дальнейших изменений. По крайней мере, это мой опыт.

аюсь зарегистрировать запрос, используя Spring 5 WebClient. Ты хоть представляешь, как мне этого добиться?

(Я использую Spring 5 и Spring boot 2)

Код выглядит следующим образом:

try {
    return webClient.get().uri(url, urlParams).exchange().flatMap(response -> response.bodyToMono(Test.class))
            .map(test -> xxx.set(test));
} catch (RestClientException e) {
    log.error("Cannot get counter from opus", e);
    throw e;
}
 Brian Clozel12 сент. 2017 г., 11:06
Спасибо! Не могли бы вы также привести пример того, что вы хотели бы войти? URI запроса?

Ответы на вопрос(3)

Spring Boot> = 2.1.0

Добавьте следующее в application.properties:

logging.level.org.springframework.web.reactive.function.client.ExchangeFunctions=TRACE
spring.http.log-request-details=true

Вторая строка приводит к тому, что заголовки включаются в журнал.

Spring Boot <2.1.0

Добавьте следующее в application.properties:

logging.level.org.springframework.web.reactive.function.client.ExchangeFunctions=TRACE

Вместо второй строки выше, вам нужно объявить класс следующим образом:

@Configuration
static class LoggingCodecConfig {

    @Bean
    @Order(0)
    public CodecCustomizer loggingCodecCustomizer() {
        return (configurer) -> configurer.defaultCodecs()
                .enableLoggingRequestDetails(true);
    }

}

Предоставленоэто ответ Брайана Клозела

 Tobske03 янв. 2019 г., 10:49
Мне нравится версия для Spring Boot> = 2.1.0, но она только логиheaders={masked}в моем случае. Есть идеи почему?
 Fletch04 янв. 2019 г., 11:39
@Tobske второй линке из раздела> = 2.1.0 заботится о замаскированных заголовках, вам не нужно никаких дальнейших изменений. По крайней мере, это мой опыт.
 Tobske03 янв. 2019 г., 10:53
Хорошо, иногда я должен искать решение немного дольше:docs.spring.io/spring/docs/current/spring-framework-reference/..., Это объясняет, почему он печатает в маске и как его можно отключить.

reactor.ipc.netty.channel.ChannelOperationsHandler делает это для вас. Просто настройте свою систему регистрации для этого класса, чтобы регистрировать на уровне DEBUG:

2017-11-23 12:52:04.562 DEBUG 41449 --- [ctor-http-nio-5] r.i.n.channel.ChannelOperationsHandler   : [id: 0x9183d6da, L:/127.0.0.1:57681 - R:localhost/127.0.0.1:8000] Writing object DefaultFullHttpRequest(decodeResult: success, version: HTTP/1.1, content: UnpooledByteBufAllocator$InstrumentedUnpooledUnsafeHeapByteBuf(ridx: 0, widx: 0, cap: 0))
GET /api/v1/watch/namespaces/default/events HTTP/1.1
user-agent: ReactorNetty/0.7.1.RELEASE
host: localhost:8000
accept-encoding: gzip
Accept: application/json
content-length: 0

Один из способов уменьшить количество ошибок - не писать код, когда это возможно.

Ноя 2018:

С участиемspring-webflux:5.1.2.RELEASEвышеупомянутое больше не работает. Вместо этого используйте следующее:

logging.level.org.springframework.web.reactive.function.client.ExchangeFunctions=DEBUG
...
2018-11-06 20:58:58.181 DEBUG 20300 --- [           main] o.s.w.r.f.client.ExchangeFunctions       : [2026fbff] HTTP GET http://localhost:8080/stocks/search?symbol=AAPL
2018-11-06 20:58:58.451 DEBUG 20300 --- [ctor-http-nio-4] o.s.w.r.f.client.ExchangeFunctions       : [2026fbff] Response 400 BAD_REQUEST

Чтобы зарегистрировать заголовки или тело формы, установите вышеTRACE уровень; Однако этого недостаточно

ExchangeStrategies exchangeStrategies = ExchangeStrategies.withDefaults();
exchangeStrategies
    .messageWriters().stream()
    .filter(LoggingCodecSupport.class::isInstance)
    .forEach(writer -> ((LoggingCodecSupport)writer).setEnableLoggingRequestDetails(true));

client = WebClient.builder()
    .exchangeStrategies(exchangeStrategies)
 Abhijit Sarkar23 мар. 2018 г., 17:52
 Michael Piefel23 мар. 2018 г., 15:41
Можно ли также записать ответ?
 Pavan Kumar06 мар. 2018 г., 08:40
Я предпочитаю это решение в ограниченных и контролируемых средах как более простой вариант для отладки. Это не всегда рекомендуется, так как это может раскрыть некоторую конфиденциальную информацию в заголовках и т. Д. Если пользовательский фильтр подключен, у него есть возможность анализировать и скрывать такую ​​конфиденциальную информацию.
 Abhijit Sarkar06 мар. 2018 г., 17:12
@PavanKumar Любой вид проводной передачи может регистрировать чувствительные заголовки, такие какAuthorization, ФП не просила скрывать их, ноесли это требование,тогда код может быть написан. Обычно такие заголовки допустимо регистрировать на уровне DEBUG.
Решение Вопроса

ExchangeFilterFunction

Просто добавь кастомlogRequest фильтр при созданииWebClient с помощьюWebClient.Builder.

Вот пример такого фильтра и как добавить его вWebClient.

@Slf4j
@Component
public class MyClient {

    private final WebClient webClient;

    // Create WebClient instance using builder.
    // If you use spring-boot 2.0, the builder will be autoconfigured for you
    // with the "prototype" scope, meaning each injection point will receive
    // a newly cloned instance of the builder.
    public MyClient(WebClient.Builder webClientBuilder) {
        webClient = webClientBuilder // you can also just use WebClient.builder()
                .baseUrl("https://httpbin.org")
                .filter(logRequest()) // here is the magic
                .build();
    }

    // Just example of sending request
    public void send(String path) {
        ClientResponse clientResponse = webClient
                .get().uri(uriBuilder -> uriBuilder.path(path)
                        .queryParam("param", "value")
                        .build())
                .exchange()
                .block();
        log.info("Response: {}", clientResponse.toEntity(String.class).block());
    }

    // This method returns filter function which will log request data
    private static ExchangeFilterFunction logRequest() {
        return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
            log.info("Request: {} {}", clientRequest.method(), clientRequest.url());
            clientRequest.headers().forEach((name, values) -> values.forEach(value -> log.info("{}={}", name, value)));
            return Mono.just(clientRequest);
        });
    }

}

Тогда просто позвонитеmyClient.send("get"); и журнал сообщений должен быть там.

Пример вывода:

Request: GET https://httpbin.org/get?param=value
header1=value1
header2=value2
 Pavan Kumar06 мар. 2018 г., 08:44
ИМО, ссылаясьblock() побеждает цель использования веб-клиента. Мы можем зарегистрировать запрос, используя фильтр, но не уверены, как зарегистрировать ответ отMono<ClientResponse> без блокировки.
 Gaurav Singh10 авг. 2018 г., 14:47
Как получить тело запроса отclientRequest?
 Ruslan Stelmachenko06 мар. 2018 г., 18:39
@PavanKumar Theblock() Звоните сюда только для демонстрации. Фильтр регистрации запросов будет работать в любом случае. Для регистрации ответа вы можете написать ещеExchangeFilterFunction и зарегистрируйте ответ. Но будьте осторожны, когда вы регистрируете тело ответа - из-за его потоковой природы его можно использовать только один раз без оболочки.

Ваш ответ на вопрос