WebClient 5.3+ 交换与 exchangeToMono。一起提取 cookie 和 body
WebClient 5.3+ exchange vs exchangeToMono. Extracting cookies and body together
我目前正在尝试处理通过 webClient 返回的整个请求。我需要能够阅读它附带的 body 和 cookies。但是,我目前在一次通话中同时执行这两项操作时遇到问题。下面我有两种方式来获取我想要的数据。我对使用 lambdas 和 webClient 还很陌生。我确实意识到 exchangeToMono() 是对 return Mono 或 Flux 的最新方法调用,因为在 exchange() 中发现了可能的内存泄漏。
我想说 subscribing() 到 return monoBody 可能对我有帮助,但到目前为止,我也没有运气以这种方式提取数据。谢谢大家的意见。
Mono<String> monoBody = webBuilder.build()
.get()
.uri(baseURI + "?Level=&pageSize=50&pageNo=&name=&id=&authToken=" + sessionToken)
.accept(MediaType.ALL)
.header("authToken", sessionToken)
.header("x-Token", sessionToken)
.header("X-token-X", sessionToken)
.header("Ref", ref)
.exchangeToMono(clientResponse -> clientResponse.bodyToMono(String.class));
Mono<MultiValueMap<String,ResponseCookie>> monoMap = webBuilder.build()
.get()
.uri(baseURI + "?Level=&pageSize=50&pageNo=&unitName=&id=&authToken=" + sessionToken)
.accept(MediaType.ALL)
.header("authToken", sessionToken)
.header("x-Token", sessionToken)
.header("X-token-X", sessionToken)
.header("Ref", ref)
.exchangeToMono(clientResponse -> Mono.fromCallable(()-> clientResponse.cookies() ));
关于 Reactor API(由 WebClient 使用)要记住的关键是,您总是将操作组合成一个 'plan' 要做什么,然后在某个时候(订阅)您执行整个计划。
在您的情况下,您已经找到了两种获取所需信息的方法,但是对于 Reactive 流,您只能在流中的任何一点拥有一种类型,因此如果您需要两种类型的数据,您总是可以将它们组合成一个复合对象。
record DataWithCookies(MultiValueMap<String,ResponseCookie> cookies, String body){}
...
Mono<DataWithCookies> dataWithCookies =
webBuilder.build()
.get()
.uri(baseURI + "?Level=&pageSize=50&pageNo=&unitName=&id=&authToken=" + sessionToken)
.accept(MediaType.ALL)
.header("authToken", sessionToken)
.header("x-Token", sessionToken)
.header("X-token-X", sessionToken)
.header("Ref", ref)
.exchangeToMono(response ->
response.bodyToMono(String.class)
.map(stringBody -> new DataWithCookies(
stringBody,
response.cookies())
)
);
我使用了 previewed JDK 16 feature "Records" for brevity,但您可以使用简单的 class 作为 DataWithCookies
。
您现在有了一个 Mono,它将与 cookie 一起生成 body。为了便于阅读,您甚至可能想将该 lambda 提取到私有方法中。
...
.exchangeToMono(this::extractBodyAndCookies);
...
private DataWithCookies extractBodyAndCookies(final ClientResponse response) {
return response.bodyToMono(String.class)
.map(stringBody -> new DataWithCookies(stringBody,
response.cookies())
);
}
另一种选择是使用 Tuples.of(stringBody, response.cookies())
,这样可以避免在组合两个数据的同时创建另一种类型。
我目前正在尝试处理通过 webClient 返回的整个请求。我需要能够阅读它附带的 body 和 cookies。但是,我目前在一次通话中同时执行这两项操作时遇到问题。下面我有两种方式来获取我想要的数据。我对使用 lambdas 和 webClient 还很陌生。我确实意识到 exchangeToMono() 是对 return Mono 或 Flux 的最新方法调用,因为在 exchange() 中发现了可能的内存泄漏。 我想说 subscribing() 到 return monoBody 可能对我有帮助,但到目前为止,我也没有运气以这种方式提取数据。谢谢大家的意见。
Mono<String> monoBody = webBuilder.build()
.get()
.uri(baseURI + "?Level=&pageSize=50&pageNo=&name=&id=&authToken=" + sessionToken)
.accept(MediaType.ALL)
.header("authToken", sessionToken)
.header("x-Token", sessionToken)
.header("X-token-X", sessionToken)
.header("Ref", ref)
.exchangeToMono(clientResponse -> clientResponse.bodyToMono(String.class));
Mono<MultiValueMap<String,ResponseCookie>> monoMap = webBuilder.build()
.get()
.uri(baseURI + "?Level=&pageSize=50&pageNo=&unitName=&id=&authToken=" + sessionToken)
.accept(MediaType.ALL)
.header("authToken", sessionToken)
.header("x-Token", sessionToken)
.header("X-token-X", sessionToken)
.header("Ref", ref)
.exchangeToMono(clientResponse -> Mono.fromCallable(()-> clientResponse.cookies() ));
关于 Reactor API(由 WebClient 使用)要记住的关键是,您总是将操作组合成一个 'plan' 要做什么,然后在某个时候(订阅)您执行整个计划。
在您的情况下,您已经找到了两种获取所需信息的方法,但是对于 Reactive 流,您只能在流中的任何一点拥有一种类型,因此如果您需要两种类型的数据,您总是可以将它们组合成一个复合对象。
record DataWithCookies(MultiValueMap<String,ResponseCookie> cookies, String body){}
...
Mono<DataWithCookies> dataWithCookies =
webBuilder.build()
.get()
.uri(baseURI + "?Level=&pageSize=50&pageNo=&unitName=&id=&authToken=" + sessionToken)
.accept(MediaType.ALL)
.header("authToken", sessionToken)
.header("x-Token", sessionToken)
.header("X-token-X", sessionToken)
.header("Ref", ref)
.exchangeToMono(response ->
response.bodyToMono(String.class)
.map(stringBody -> new DataWithCookies(
stringBody,
response.cookies())
)
);
我使用了 previewed JDK 16 feature "Records" for brevity,但您可以使用简单的 class 作为 DataWithCookies
。
您现在有了一个 Mono,它将与 cookie 一起生成 body。为了便于阅读,您甚至可能想将该 lambda 提取到私有方法中。
...
.exchangeToMono(this::extractBodyAndCookies);
...
private DataWithCookies extractBodyAndCookies(final ClientResponse response) {
return response.bodyToMono(String.class)
.map(stringBody -> new DataWithCookies(stringBody,
response.cookies())
);
}
另一种选择是使用 Tuples.of(stringBody, response.cookies())
,这样可以避免在组合两个数据的同时创建另一种类型。