我有一个有两个端点的公共API,我必须从第一个GET端点获取一个对象数组作为Flux,然后调用第二个(内部调用)GET端点Mono(Mono包含对象列表),在那里我必须通过id找到一个内部对象,然后使用找到的对象(列表)过滤器第一个Flux(每个都包含列表)
我试着用这种方式,但它变成了一个永远的流
public class Test {
String baseUrl = "http://some-site.com/";
private final WebClient webClient = WebClient.create(baseUrl);
@SneakyThrows
public Flux<One> getObjOneFlux(String id) {
Flux<One> oneFlux = loadObjOnes();
Mono<Two> twoMono = loadObjTwo();
return oneFlux.filterWhen(one -> twoMono.map(two -> one.getOneInternalList()
.stream()
.map(One.OneInternal::getName).toList()
.containsAll(
two.getTwoInternalList().stream()
.filter(s -> s.getId().equals(id))
.findFirst().get().getOptions()
)
)
);
}
public Flux<One> loadObjOnes() {
return webClient.get()
.uri(uriBuilder -> uriBuilder.path("/ObjOne").build())
.exchange()
.flatMap(res -> res.bodyToMono(ObjOneResponse.class))
.flatMapIterable(res -> res)
.map(t ->
One.builder()
.id(t.getId())
.mark(t.getMark())
.oneInternalList(t.getOneInternalList())
.build());
}
public Mono<Two> loadObjTwo() {
return webClient.get()
.uri(uriBuilder -> uriBuilder.path("/ObjTwo").build())
.exchange()
.flatMap(res -> res.bodyToMono(Two.class))
.map(s -> Two.builder()
.twoInternalList(s.getTwoInternalList())
.build()).delayElement(Duration.ofSeconds(3));
}
}
@Data
@Builder
class One {
private String id;
private String mark;
private List<OneInternal> oneInternalList;
@Data
@Builder
public static final class OneInternal {
private String name;
}
}
@Data
@Builder
class Two {
private List<TwoInternal> twoInternalList;
@Data
@Builder
public static final class TwoInternal {
private List<String> options;
private String id;
}
}
class ObjOneResponse extends ArrayList<One> {
}
1条答案
按热度按时间3z6pesqy1#
你的问题是什么?实现看起来不错,至少对于快乐流来说。看,我已经提取了变量
namesFromOne
和optionsFromTwo
。我看到唯一的问题是
.findFirst().get()
。理想情况下,您希望在那里返回false,而不是抛出异常,因此您可以做的事情如下所示:一些小/简单测试:
正如我所看到的,你的过滤工作。也许你可以考虑一下你的模型,因为
TwoInternal
看起来很像类One
,所以也许你可以重用那里的一些东西。