使用新参数重复 WebClient get

Repeat a WebClient get with new parameters

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

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
}

我需要的是能够重复此调用,但添加一个请求参数,该参数基于 link header 的一部分和 "next" 相对值。

我看到有人提到使用展开或重复,但我不确定如何使用它们。我知道必须使用交换来获取 clientResponse,这样我才能获得 headers。

这个问题可能比较模糊,所以如果需要我可以提供任何说明。

谢谢!

更新

我一直在尝试各种方法并找到了一些几乎可行的方法。

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();
            });
}

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

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

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();