我试图使用Spring5 WebClient记录一个请求。你知道我怎么能做到这一点吗?
(我使用Spring 5和Spring 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;
}
发布于 2017-10-21 20:32:42
您可以使用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. 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
编辑
一些人在评论中指出,block()
是糟糕的实践等等。我想澄清一下:这里的block()
调用只是为了演示目的。无论如何,请求日志记录筛选器都会工作。您不需要将block()
添加到代码中才能使ExchangeFilterFunction
工作。您可以使用WebClient
以通常的方式执行http调用,链接方法并在堆栈上返回Mono
,直到有人订阅它为止。答案的唯一相关部分是logRequest()
过滤器。您可以完全忽略send()
方法--它不是解决方案的一部分--它只是演示了过滤器的工作原理。
一些人还询问如何记录回复。要记录响应,可以编写另一个ExchangeFilterFunction
并将其添加到WebClient
中。您可以使用ExchangeFilterFunction.ofResponseProcessor
助手来实现这个目的,就像使用ExchangeFilterFunction.ofRequestProcessor
一样。您可以使用ClientResponse
的方法获取标头/cookie等。
// 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)来完成此操作。请看马修·布克特的回答以获得这个想法。
发布于 2019-04-22 07:22:45
您可以使用netty记录请求/响应,方法是要求它执行窃听操作,如果您像这样创建Spring,那么它就启用了窃听选项。
WebClient webClient = WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(
HttpClient.create().wiretap(true)
))
.build()
然后让您的日志设置:
logging.level.reactor.netty.http.client.HttpClient: DEBUG
这将记录请求/响应的所有内容(包括主体),但格式并不是HTTP特有的,因此可读性不强。
发布于 2021-01-29 18:18:29
在SpringBoot2.4.0中,HttpClient的wiretap()方法具有可以传递的附加参数,以普通人类可读的格式显示完整的请求/响应头和正文。使用格式(AdvancedByteBufFormat.TEXTUAL)。
HttpClient httpClient = HttpClient.create()
.wiretap(this.getClass().getCanonicalName(), LogLevel.DEBUG, AdvancedByteBufFormat.TEXTUAL);
ClientHttpConnector conn = new ReactorClientHttpConnector(httpClient);
WebClient client = WebClient.builder()
.clientConnector(conn)
.build();
结果:
POST /score HTTP/1.1
Host: localhost:8080
User-Agent: insomnia/2020.5.2
Content-Type: application/json
access_:
Authorization: Bearer eyJ0e....
Accept: application/json
content-length: 4506
WRITE: 4506B {"body":{"invocations":[{"id":....
READ: 2048B HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 2271
Server: Werkzeug/1.0.1 Python/3.7.7
Date: Fri, 29 Jan 2021 18:49:53 GMT
{"body":{"results":[.....
https://stackoverflow.com/questions/46154994
复制相似问题