我对弹簧反应式编程有点新意。我目前正在使用spring-boot-starter-webflux:2.0.0.M5开发一个应用程序。
我有一个Foodtruck mongodb模型,其中包含菜单:
@Document(collection = "Foodtruck")
@lombok.Getter
@lombok.Setter
@lombok.NoArgsConstructor
@lombok.AllArgsConstructor
public class Foodtruck {
@Id
private String id;
@URL
private String siteUrl;
@NotBlank
private String name;
private String description;
@NotBlank
private String address;
private List<Menu> menus;
@JsonIgnore
private GridFS image;
}
以下是菜单的模型:
@lombok.Getter
@lombok.Setter
@lombok.NoArgsConstructor
@lombok.AllArgsConstructor
@Document(collection = "menus")
public class Menu {
@Id
private String id;
private List<DayOfWeek> days;
@NotBlank
private String label;
private String description;
private Double price;
private List<Dish> dishes;
@JsonIgnore
private GridFS image;
}
要获取我的所有菜单,我首先需要获取所有餐馆,然后合并所有获得的 Flux ,并通过我的休息控制器返回。
以下是我从其余资源调用的服务:
@Service
public class MenuServiceImpl implements MenuService {
FoodtruckService foodtruckService;
public MenuServiceImpl(FoodtruckService foodtruckService) {
this.foodtruckService = foodtruckService;
}
@Override
public Flux<Menu> getAllMenus() {
Flux<Menu> allMenuFlux = Flux.empty();
Flux<Foodtruck> foodtruckFlux = foodtruckService.getAllFoodtrucks();
foodtruckFlux.toStream().forEach(foodtruck -> {
Flux<Menu> currentMenuFlux = Flux.fromIterable(foodtruck.getMenus());
allMenuFlux.mergeWith(currentMenuFlux);
});
return allMenuFlux;
}
}
mergeWith似乎没有向 allMenuFlux 添加任何内容。我想我在这里有一个理解问题。
我已经阅读了文档,测试了其他方法,如concat或zip,但它并没有像我希望的那样交错磁通事件。我无法正确合并这些 Flux 。 我还认为有一种更好的方法可以通过菜单存储库获取mongo嵌入式文档,因为我的方法似乎有点矫枉过正,从长远来看可能会导致性能问题。我试过了,但是没有用。
编辑: 尝试以下代码后(确保我的列表不为空),生成的 fluxtest3 变量正确合并:
Flux<Menu> allMenuFlux = Flux.empty();
Flux<Foodtruck> foodtruckFlux = foodtruckService.getAllFoodtrucks();
List<Foodtruck> test = foodtruckFlux.collectList().block();
Flux<Menu> fluxtest1 = Flux.fromIterable(test.get(0).getMenus());
Flux<Menu> fluxtest2 = Flux.fromIterable(test.get(1).getMenus());
Flux<Menu> fluxtest3 = fluxtest1.mergeWith(fluxtest2);
但这不是我想要的。为什么不使用空助焊剂作为母通量。
我在这里缺少什么?
提前感谢您的帮助。
答案 0 :(得分:2)
我认为这里有一些误解。
如果您将Flux
转换为Collection
,Stream
或类似内容,然后将某些内容转换回Flux
,那么您肯定在做有问题。这些类强制您的管道收集多个元素,然后处理它们,然后将它们转换回Flux
。几乎在所有情况下,只有Flux
提供的操作才能实现这一点。
Flux
上的方法不会更改Flux
,但会创建具有其他行为的新实例。所以如果你有这样的代码:
Flux<Menu> allMenuFlux = Flux.empty();
Flux<Foodtruck> foodtruckFlux = foodtruckService.getAllFoodtrucks();
foodtruckFlux.toStream().forEach(foodtruck -> {
Flux<Menu> currentMenuFlux = Flux.fromIterable(foodtruck.getMenus());
allMenuFlux.mergeWith(currentMenuFlux);
});
返回allMenuFlux;
每次调用allMenuFlux.mergeWith(currentMenuFlux);
时,都会创建一个新的Flux
,以便垃圾收集器可以处理它。 allMenuFlux
仍然是你开始的那个空的“Flux。”
您真正想要的是:
return foodtruckService.getAllFoodtrucks()
.flatMap(Foodtruck::getMenus);
请参阅flatMap
的文档。 flatMap
和mergeWith
之间的区别在于mergeWith
保留了原始元素。如果您的用例中没有,则多余是多余的。
奖金:您的其他问题
Flux<Menu> fluxtest1 = Flux.fromIterable(test.get(0).getMenus());
Flux<Menu> fluxtest2 = Flux.fromIterable(test.get(1).getMenus());
Flux<Menu> fluxtest3 = fluxtest1.mergeWith(fluxtest2);
此处您不会返回原始fluxtest1
,而是返回新生成的fluxtest2
。因此它确实有效。