gpt4 book ai didi

spring-mvc - Spring Webflux 与 Spring MVC - 使用 doOnEach 时发出空值

转载 作者:行者123 更新时间:2023-12-04 06:34:54 31 4
gpt4 key购买 nike

我正在尝试使用 Spring Webflux 和 Spring MVC,遇到了一个有趣的案例。

从一个简单的 Controller 开始:

@GetMapping
public Mono<String> list(final Model model) {
Flux<User> users = this.userRepository.findAll();
model.addAttribute("users", users);
return Mono.just("users/list");
}
userReposutory是定制 ConcurrentHashMap基于的实现。在这里您可以找到 findAll方法:
@Override
public Flux<User> findAll() {
return Flux.fromIterable(this.users.values());
}

每当我尝试返回访问“用户/列表” View 时,一切似乎都正常工作。

但是,如果我尝试使用惯用的响应式(Reactive)方法重写 Controller ,问题就会开始出现:
@GetMapping
public Mono<String> list(final Model model) {
return this.userRepository.findAll()
.collectList()
.doOnEach(users -> model.addAttribute("users", users.get()))
.map(u -> "users/list");
}

如果我到达终点,我会在日志中得到这个:
java.lang.IllegalArgumentException: ConcurrentModel does not support null attribute value
at org.springframework.util.Assert.notNull(Assert.java:193)
at org.springframework.ui.ConcurrentModel.addAttribute(ConcurrentModel.java:75)
at org.springframework.ui.ConcurrentModel.addAttribute(ConcurrentModel.java:39)
at com.baeldung.lss.web.controller.UserController.lambda$list$0(UserController.java:37)
at reactor.core.publisher.FluxDoOnEach$DoOnEachSubscriber.onError(FluxDoOnEach.java:132)

显然,有些流浪 null正在那里。让我们急切地过滤掉所有这些:
@RequestMapping
public Mono<String> list(final Model model) {
return this.userRepository.findAll()
.filter(Objects::nonNull)
.collectList()
.filter(Objects::nonNull)
.doOnEach(users -> model.addAttribute("users", users.get()))
.map(u -> "users/list");
}

同样的问题,但是...如果我把所有东西都塞进 map()打电话,一切又正常了:
@GetMapping
public Mono<String> list(final Model model) {
return this.userRepository.findAll()
.collectList()
.map(users -> {
model.addAttribute("users", users);
return "users/list";
});
}

虽然,将副作用放在 map 中不是最优的。

任何想法 doOnEach() 出了什么问题这里?

最佳答案

非常好的问题。让我们看看 JavaDocs说说 doOnEach :

public final Mono<T> doOnEach(Consumer<? super Signal<T>>
signalConsumer)

Add behavior triggered when the Mono emits an item, fails with an error or completes successfully. All these events are represented as a Signal that is passed to the side-effect callback



好奇的。 usersdoOnEach(users -> ...)不是 List<User>但是一个 Signal<List<User>> .此 Signal<T>对象不会为空,这就解释了为什么 filter第二个版本中的方法不起作用。

JavaDocs for Signal<T> get()方法明确标记为 @Nullable并且只会在下一个项目到达时返回一个非空值。如果生成完成或错误信号,则返回 null .

解决方案:
  • 使用 doOnNext相反:您对下一个值感兴趣,而不是来自源流的任何信号。
  • doOnEach 中进行空检查lambda:这也可以,但因为你对其他事件不感兴趣,所以是多余的。
  • 关于spring-mvc - Spring Webflux 与 Spring MVC - 使用 doOnEach 时发出空值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50314514/

    31 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com