理解问题 switchIfEmpty 和 switchIfEmpty

Understanding problems switchIfEmpty and switchIfEmpty

我尝试使用 kotlin/webflux/r2dbc:postgresql 编写网络应用程序 但我有问题。我不明白为什么 switchIfEmpty 在工作结果 hackerService.resetPassword 不为空时调用

控制器

@PostMapping("/reset/password/{link}", consumes = [MediaType.APPLICATION_FORM_URLENCODED_VALUE])
    fun resetPassword(@PathVariable link: String, req: ResetPassword): Mono<ResponseEntity<String>> {
        return userservice.resetPassword(link, req)
                .map { ResponseEntity.ok("OK") }
                .switchIfEmpty(Mono.just(ResponseEntity.notFound().build()))
    }

服务

fun resetPassword(link: String, resetPassword: ResetPassword): Mono<Void> {
        BLEException.checkArgument(resetPassword.newPassword == resetPassword.checkPassword, PASSWORD_NOT_MATCH)
        return resetPasswordRepository.findByLink(link)
                .flatMap { updateAccount(it.userId, password = resetPassword.newPassword) }
                .flatMap { resetPasswordRepository.deleteByUserId(it.id!!) }
    }

方法 updateAccount 正在设置新密码并且 resetPasswordRepository.deleteByUserId 从 table 中删除行。 而且这种方法有效,我希望 resetPassword

不会为空 Mono

但最终我遇到了 404 错误。

我很乐意提供任何帮助,谢谢

如果resetPasswordRepository是一个spring数据ReactiveCrudRepository,那么所有delete*()方法的return类型就是Mono<Void>

Mono<Void>是空Mono的类型。

因此,switchIsEmpty 将始终被调用,因为从 resetPassword 编辑的对象 return 是一个空的 Mono。

我可以想出两种方法来解决这个问题

  1. return a Mono.error 而不是在服务中为空并将错误映射到控制器中的 ResponseStatusException
return resetPasswordRepository.findByLink(link)
    .switchIfEmpty(Mono.error(UserNotFound()))

  1. 使用 .then*() 操作将 delete* 的结果从 Mono<Void> 映射到其他东西,比如删除的实体。当然,您需要更改服务方法的结果类型
    .flatMap { resetPasswordRepository.deleteByUserId(it.id!!).thenReturn(it) }