java - 使用新参数重复 WebClient 获取

标签 java spring-boot http-headers spring-webflux

我正在开发一个 Spring WebFlux 应用程序,并且我有一个 Web 适配器,用于调用我使用的外部 api 方法。其中一个 api 具有使用带有 rel="next"的链接 header 的分页结果。我需要调用此 api,直到下一个链接不存在,但我不确定如何实现此目的。以下是我当前使用的基本调用:

public Flux<ItemDto> getAllItems(){
   return webClient.get() //The headers and base url for the api are defined in the constructor
        .uri("/api/items?limit=200") //limit is the number of items returned with 200 being the maximum
        .retrieve()
        .bodyToFlux(Map.class)
        .map(ItemConverter::mapValueToItemDto);//This is just a conversion method that handles mapping
}

我需要的是能够重复此调用,但添加一个基于带有“下一个”rel 值的链接 header 部分的请求参数。

我见过提到使用展开或重复,但我不确定如何准确使用它们。我知道使用交换对于获取 clientResponse 是必要的,这样我就可以获得 header 。

这个问题可能相当模糊,所以如果需要的话我可以提供任何澄清。

谢谢!

更新

我一直在尝试各种事情,并发现了一些几乎可行的东西。

public Flux<ItemDto> getAllItems(){
   return recursiveMethod("")//Start with the first page basically
      .flatMap(clientResponse ->
           clientResponse.bodyToFlux(Map.class)
                .map(ItemConverter::mapValueToItemDto));
}

private Flux<ClientResponse> recursiveMethod(String after){
   return webClient.get()
            .uri("/api/items?limit=3" + after) //The test list I am using is only 9 items so I'm using 3 for good results
            .exchange()
            .expand(clientResponse -> {
                List<String> links = clientResponse.headers().asHttpHeaders().getValuesAsList("LINK");
                if(links.stream().anyMatch(link->link.contains("rel=\"next\""))){
                    for (String link : links){
                        if (link.contains("rel=\"next\"")){
                            return recursiveMethod("&" + link.substring(link.indexOf("after="), link.indexOf("&"))); 
                            //The header link has limit and after switched, that's why this looks a little odd
                        }
                    }
                }
                return Flux.empty();
            });
}

唯一的问题是它最终会重复最后一个“页面”,例如:项目 1、项目 2、项目 3、项目 4、项目 5、项目 6、项目 7、项目 8、项目 9、项目 7、第 8 项、第 9 项。 不确定这是由于我设置的递归还是 Flux 或者因为我可能误用了扩展方法。

最佳答案

经过大量试验和错误并找到特定部分的解决方案后,我找到了适合我的解决方案。

public Flux<ItemDto> getAllItems() {
    webClient.get()
            .uri("/api/items?limit=1")//Used one to test
            .exchange()
            .expand(clientResponse -> {
                List<String> links = clientResponse.headers().asHttpHeaders().getValuesAsList("LINK");
                if(links.stream().anyMatch(link->link.contains("rel=\"next\""))){
                    for (String link : links){
                        if (link.contains("rel=\"next\"")){
                            return webClient.get()
                                    .uri("/api/items?limit=1&" + link.substring(link.indexOf("after="), link.indexOf("&")))
                                    .exchange();
                        }
                    }
                }
                return Flux.empty();
            })
            .flatMap(clientResponse ->
                    clientResponse.bodyToFlux(Map.class)
                            .map(ItemConverter::mapValueToItemDto));
}

不需要任何递归。使用扩展更合适。现在,其中的一部分(见下文)实际上可以分解为自己的方法,但由于它只有几行,我选择不这样做。

webClient.get()
   .uri("/api/items?limit=1" + after)//This after bit would be like what was passed as an argument before
   .exchange();

关于java - 使用新参数重复 WebClient 获取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54577893/

相关文章:

java - 如何让Java程序在输入 "Q"时退出,问题是默认输入变量是double

java - Spring Security 6 返回错误 401 而不是 404

java - 如何将ThreadLocal从父线程复制到多个子线程?

javascript - 来自 JavaScript 的 HTTP 请求使用包含 header 的原始消息

php - 为什么 PHP $_SERVER 变量中的 HTTP 响应代码不可用?

javascript - 如何使用 header 和数据创建对服务器的 javascript POST 请求

java - fragment 中更改主题(setTheme)类android Utils "this"错误

java - Hibernate 不断为我的枚举创建表

java - Android:无法解密值

java - 在由 docker 拉取的 Spring Boot 应用程序中实现 LetsEncrypt