WebClient 5.3+ 交换与 exchangeToMono。一起提取 cookie 和 body

Posted

技术标签:

【中文标题】WebClient 5.3+ 交换与 exchangeToMono。一起提取 cookie 和 body【英文标题】:WebClient 5.3+ exchange vs exchangeToMono. Extracting cookies and body together 【发布时间】:2021-03-20 11:05:40 【问题描述】:

我目前正在尝试使用通过 webClient 返回的整个请求。我需要能够阅读它附带的 bodycookies。但是,我目前在一个电话中同时处理这两个问题。下面我有两种方法来获取我想要的数据。我对使用 lambdas 和 webClient 很陌生。我确实意识到 exchangeToMono() 是返回 Mono 或 Flux 的最新方法调用,因为在 exchange() 中可能存在内存泄漏。 我想说订阅()返回 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() ));
    

【问题讨论】:

【参考方案1】:

关于 Reactor API(由 WebClient 使用)要记住的关键是您始终将操作组合成一个“计划”,然后在某个时间点(订阅)执行整个计划。

在您的情况下,您已经找到了两种获取所需信息的方法,但是对于 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,但您可以为DataWithCookies 使用一个简单的类。

您现在有了一个 Mono ,它将产生主体和 cookie。您甚至可能想将该 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 5.3+ 交换与 exchangeToMono。一起提取 cookie 和 body的主要内容,如果未能解决你的问题,请参考以下文章

思科模拟器Packet tracert 5.3 我想用1 PC连接一交换机或者路由器,怎么启动超级终端,

如何将 WebClient 与 .Net Core 一起使用?

将 CookieContainer 与 WebClient 类一起使用

5.3排序算法和程序调试

WebClient 与 RestTemplate

043.希尔排序