Mongo Flux / Mono获取对象

时间:2018-06-28 07:23:16

标签: java mongodb spring-boot project-reactor

我想从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))
    ;

1 个答案:

答案 0 :(得分:0)

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

为什么您不能阻止

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

您的答案和一些小改进

首先,map可以简化,因为nullFlux中不允许使用Mono值。如果该值不在数据库中,则Spring数据ReactiveCrudRepository将返回一个空的Mono,不要与发出Mono的{​​{1}}混淆:

null

vs

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

我还认为,对于---|-> onComplete() ,您打算包装DB错误,但“用户存在”情况除外?如果是这样,则此onErrorResume的放置是错误的,因为它类似于也会捕获onErrorResume的{​​{1}}。将其放在catch(Throwable e)之前 。您也可以直接从地图内投掷。

因此,这归结为检测空UserByEmailExistException与值map,用异步数据库保存替换空的Mono,而用Mono替换空的值:

TL; DR给我代码了

onError