使用新参数重复 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();
我正在开发一个 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();