我开始使用Project reactor和一个我很难挣扎的地方,我怎么把Mono和Flux的东西结合起来。这是我的用例:
public interface GroupRepository {
Mono<GroupModel> getGroup(Long groupId);
}
public interface UserRepository {
Flux<User> getUsers(Set<Long> userIds);
}
Mono<GroupModel> groupMono = getGroup(groupId);
Flux<User> userFlux = getUsers(Set<Long> users);
//run above instrtuction in parallel and associate user to group.
现在我想要实现的是:
如何组合UserFlux的响应并将这些用户与该组相关联,例如group.addUsers(userfromFlux)。
有人可以帮助您组合来自userFlux和groupMono的结果。我想我使用像Zip这样的东西,然后它从源头做一对一的映射。就我而言,我需要做1到N的映射。在这里,我有一个组,但我需要添加到该组的多个用户。返回Mono<List<Users>
然后使用单声道的zip运算符并提供这里提到的组合器是一个好主意
public static <T1, T2, O> Flux<O> zip(Publisher<? extends T1> source1,
Publisher<? extends T2> source2,
final BiFunction<? super T1, ? super T2, ? extends O> combinator)
?
答案 0 :(得分:3)
我认为Flux.combineLatest
静态方法可以帮助您:由于您的Mono
只发出1个元素,因此该元素将始终与Flux
中的每个传入值相结合。
Flux.combineLatest(arr -> new Combination((GroupModel) arr[0], (User) arr[1]),
groupMono, userFlux);
答案 1 :(得分:2)
从1到N的映射听起来类似于我在这里给出的答案:
Can you Flux.zip a mono and a flux and and repeat the mono value for every flux value?
万一该链接断开,这又是答案。我认为此方法不会具有良好的性能,因为每次都会重新计算单声道。为了获得更好的性能,如果您的Mono被慢速操作包围了,那么最好有一些缓存层。
假设您有一个通量和一个这样的单声道:
// a flux that contains 6 elements.
final Flux<Integer> userIds = Flux.fromIterable(List.of(1,2,3,4,5,6));
// a mono of 1 element.
final Mono<String> groupLabel = Mono.just("someGroupLabel");
首先,我将向您展示尝试压缩我尝试过的2的错误方式,我想其他人会尝试:
// wrong way - this will only emit 1 event
final Flux<Tuple2<Integer, String>> wrongWayOfZippingFluxToMono = userIds
.zipWith(groupLabel);
// you'll see that onNext() is only called once,
// emitting 1 item from the mono and first item from the flux.
wrongWayOfZippingFluxToMono
.log()
.subscribe();
// this is how to zip up the flux and mono how you'd want,
// such that every time the flux emits, the mono emits.
final Flux<Tuple2<Integer, String>> correctWayOfZippingFluxToMono = userIds
.flatMap(userId -> Mono.just(userId)
.zipWith(groupLabel));
// you'll see that onNext() is called 6 times here, as desired.
correctWayOfZippingFluxToMono
.log()
.subscribe();
答案 2 :(得分:0)
为其他人添加答案,我使用了Flux.zip(groupMono, userMono(holding list of users), this::biFunctionToPopulateGroupWithUsers)
。我使用这种方法而不是@Simon的建议,因为持有用户的基础组是HashSet
,并且以被动方式添加用户将不是线程安全的。但是,如果你有一个线程安全的数据结构,我会使用@Simon的建议。