【问题标题】:Mongo Flux/Mono get object/sMongo Flux/Mono 获取对象/s
【发布时间】:2018-12-07 04:30:11
【问题描述】:

我想从 Flux/Mono 中获取对象/对象。 我用

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>

我会这样做:

    Mono<UserEntity> byEmail = userRepository.findByEmail(userDto.getEmail());
    UserEntity block = byEmail.block();

我有错误:

java.lang.IllegalStateException: block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-nio-3

为什么?有什么不同的方法来获取对象/对象?

在反应式编程中如何做一些事情: 在 RequestBody 中有 UserDto。

如果没有创建用户,请检查数据库中是否存在电子邮件。

@simon-baslé 的答复更新

 return userRepository.findByEmail(userDto.getEmail())
    //rethrow DB errors as BadRequestException, except user exists
    .onErrorResume(t -> Mono.error(new BadRequestException()))
    //throwing in map is converted to onError signal
    .map(ifItGoesThereItExist-> { throw new UserByEmailExistException(); })
    //switchIfEmpty to replace an empty source with a different Mono
    .switchIfEmpty(createUser(userDto))
    //at this point, map can only receive an onNext from the createUser
    .map(u -> new ResponseEntity(u, HttpStatus.CREATED))
    ;

【问题讨论】:

  • 所以,我无法获取对象,因为我无法阻止?那么如何检查用户是否存在于数据库中并返回异常用户存在呢?
  • 如果您使用响应式编程,您应该订阅 Mono Publisher。
  • @GauravSrivastav 在这种情况下不是,Spring 框架会进行订阅

标签: java mongodb spring-boot project-reactor


【解决方案1】:

您似乎找到了答案,但让我详细说明一下。

为什么不能屏蔽

您收到的错误消息表明您尝试在不适合阻塞的特定Thread(或线程池)内恢复阻塞行为。这是 Spring Webflux(在后台,Netty)使用的线程来处理应用程序中的每个传入请求。因此,如果您阻止它,您将完全阻止您的应用程序处理新请求。

您的回答,以及一些小的改进

首先,map 可以简化,因为在 Flux 或 Mono 中不允许使用 null 值。如果值不在 DB 中,Spring Data ReactiveCrudRepository 将返回一个空的 Mono,不要与发出 null 的 Mono 混淆:

---( null )---|->
onNext(null), onComplete() // onNext(null) being forbidden

对

---|->
onComplete()

另外,我认为onErrorResume 您打算包装数据库错误,除了“用户存在”的情况?如果是这样,这个onErrorResume 的位置是错误的,因为它类似于catch(Throwable e),它也会捕获UserByEmailExistException。把它放在map 之前。也可以直接从地图内投掷。

所以这归结为检测一个空的Mono vs 值Mono,将空的替换为异步数据库保存,将值替换为onError:

TL;DR 给我代码

return userRepository.findByEmail(userDto.getEmail())
        //rethrow DB errors as BadRequestException, except user exists
        .onErrorResume(t -> Mono.error(new BadRequestException()))
        //throwing in map is converted to onError signal
        .map(ifItGoesThereItExist-> { throw new UserByEmailExistException(); })
        //switchIfEmpty to replace an empty source with a different Mono
        .switchIfEmpty(createUser(userDto))
        //at this point, map can only receive an onNext from the createUser
        .map(u -> new ResponseEntity(u, HttpStatus.CREATED))
        ;

【讨论】:

  • 非常感谢。现在我知道更多了。我刚开始反应性地思考。如果我想检查 Mono 是否为空,那么地图将不会被调用?
猜你喜欢
  • 1970-01-01
  • 2019-06-06
  • 1970-01-01
  • 2020-02-28
  • 2021-07-31
  • 2021-09-30
  • 2021-08-02
  • 2021-05-04
  • 1970-01-01
相关资源
最近更新 更多