doOnNext() 不会被调用 Spring Webflux

Sia*_*Sia 6 java reactive-programming spring-boot project-reactor spring-webflux

我是反应式编程和 Spring Webflux 的新手,我有一种方法可以从 Redis 获取一些密钥,如果该密钥为 null 或不等于指定的字符串,我想抛出异常,但嵌套的 donOnNext 方法不会被调用并被customerRepository.save(customer)触发,而必须抛出异常并打破链条。有人可以向我解释一下 Reactor API 在我的例子中是如何表现的吗?

这是我的方法:

@Override
public Mono<RegistrationVerificationResDTO> verifyCustomerAndGenerateToken(Mono<VerifyOtpReqDTO> verifyOtpReqDTO) {
    return verifyOtpReqDTO
            .doOnNext(verifyDTO -> reactiveRedisOperations
                    .opsForValue()
                    .get(RedisDictionary.OTP_KEY + verifyDTO.getPhoneNumber())
                    .filter(otp -> otp.equalsIgnoreCase(verifyDTO.getOtp()))
                    .switchIfEmpty(Mono.error(ForbiddenException::new)))
            .map(verifyDTO -> customerRepository.findById(verifyDTO.getId())
                    .orElseThrow(() -> new NotFoundException("Customer not found")))
            .doOnNext(customer -> {
                customer.setVerified(true);
                customerRepository.save(customer);
            })
            .map(customer -> new RegistrationVerificationResDTO().setAccessToken("accessToken")
                    .setRefreshToken("refreshToken")
                    .setCustomer(customer));
}
Run Code Online (Sandbox Code Playgroud)

更新:我意识到如果我们在 doOnNext 方法中创建另一个发布者,因为 spring 仅订阅最外层的发布者,内部发布者不会被触发我已经更新了我的代码,但它仍然不起作用。

Sim*_*slé 4

我猜你是说这“不起作用”,因为你无法观察customer数据库中保存的内容,即使你对第二个(最里面的)进行了(正确的)更改doOnNext

第三个doOnNext是有问题的:customerRepository.save(customer)是一个 NO-OP 假设customerRepository是一个反应性存储库,因为(惰性)Mono既不附加到主序列也不订阅。

只需将其替换doOnNextflatMap(并保留对最里面的 doOnNext 的更改switchIfEmpty),使其成为 Spring 将订阅的反应链的一部分。

  • 在“doOnNext”和“flatMap”中处理 Mono/Flux 之间存在巨大差异:Spring 确实订阅了控制器返回的外部 Mono 或 Flux,但该订阅仅传播到作为链中链接的发布者。在 `doOnNext` 中生成 Publisher 不会使其成为链中的一个链接,而从 `flatMap` 返回一个 Publisher 则可以。 (4认同)