我正在开发一个 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/