Spring Webflux结合Spring MVC使用doOnEach时抛出空值异常问题
Why does using
doOnEach with Spring WebFlux cause a null attribute exception? 这问题我之前也碰到过,核心原因其实是**doOnEach和map处理信号的逻辑完全不一样**,咱们一步步拆解:
1. doOnEach会处理所有类型的Signal信号
Reactor中的doOnEach方法接收的是Signal<T>类型的参数,这个Signal涵盖了流的三种核心事件:
onNext:携带正常的业务数据(也就是你收集到的List<User>)onError:流发生错误时的信号onComplete:流正常结束时的信号
当你的collectList()执行完成后,会先发送一个onNext信号(带着收集好的用户列表),紧接着会发送一个onComplete信号表示流结束。而当Signal是onComplete类型时,调用signal.get()会返回null——这就是你触发ConcurrentModel非空断言的直接原因。
2. 为什么map就能正常运行?
map方法只会响应onNext信号,只有当流中有正常数据传递时才会执行逻辑,完全不会处理onComplete或onError信号。所以在map里调用model.addAttribute("users", users)时,users一定是有效的非空列表,自然不会触发异常。
3. 如果一定要用doOnEach,该怎么修复?
你需要先判断当前Signal的类型,只在onNext时处理属性添加:
@GetMapping public Mono<String> list(final Model model) { return this.userRepository.findAll() .collectList() .doOnEach(signal -> { // 只处理正常的业务数据信号 if (signal.isOnNext()) { model.addAttribute("users", signal.get()); } }) .map(u -> "users/list"); }
额外提醒:关于副作用处理的最佳实践
你提到“在map中处理副作用并非最佳实践”,这点其实要结合Spring WebFlux的场景来看:Model是请求作用域的对象,在map中修改它是完全安全的,而且符合Spring的设计预期。反而doOnEach更适合做日志、监控这类和业务逻辑无关的副作用操作,不建议用来修改请求上下文相关的状态。
内容的提问来源于stack exchange,提问作者Grzegorz Piwowarek
相关产品推荐
相关产品推荐

