您可以使用 ExchangeFilterFunction 轻松完成此操作
只需在创建 using 时添加自定义筛选器即可。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. This method is NOT part of the answer
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
编辑
有些人在评论中指出这是不好的做法等。我想澄清一下:在这里打电话只是为了演示目的。请求日志记录筛选器仍将正常工作。您无需添加到代码中即可工作。您可以使用 以通常的方式执行 http 调用,链接方法并返回堆栈,直到有人订阅它。答案的唯一相关部分是过滤器。您可以完全忽略方法 - 它不是解决方案的一部分 - 它只是证明过滤器的工作原理。block()
block()
block()
ExchangeFilterFunction
WebClient
Mono
logRequest()
send()
有些人还询问如何记录响应。要记录响应,您可以编写另一个响应并将其添加到 。您可以使用 ExchangeFilterFunction.ofResponseProcessor
帮助程序来实现此目的,方法与 使用方式相同。您可以使用 ClientResponse
的方法获取标头/Cookie 等。ExchangeFilterFunction
WebClient
ExchangeFilterFunction.ofRequestProcessor
// This method returns filter function which will log response data
private static ExchangeFilterFunction logResponse() {
return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
log.info("Response status: {}", clientResponse.statusCode());
clientResponse.headers().asHttpHeaders().forEach((name, values) -> values.forEach(value -> log.info("{}={}", name, value)));
return Mono.just(clientResponse);
});
}
不要忘记将其添加到您的:WebClient
.filter(logResponse())
但要小心,不要尝试在过滤器中读取响应正文。由于它的流性质,身体只能在没有某种缓冲包装的情况下消耗一次。因此,如果您将在过滤器中读取它,则将无法在订阅者中读取它。
如果你真的需要记录正文,你可以让底层(Netty)来做到这一点。请参阅Matthew Buckett的答案来获得这个想法。