gpt4 book ai didi

spring - 如何检查 Mono 是否为空?

转载 作者:IT老高 更新时间:2023-10-28 13:32:55 26 4
gpt4 key购买 nike

我正在使用 WebFlux 框架使用 Spring Boot 2.0 和 Kotlin 开发应用程序。

我想在保存交易之前检查用户 ID 是否存在。我被困在一个简单的事情上,比如验证 Mono 是否为空。

fun createTransaction(serverRequest: ServerRequest) : Mono<ServerResponse> {
val transaction = serverRequest.body(BodyExtractors.toMono(Transaction::class.java))

transaction.flatMap {
val user = userRepository.findById(it.userId)
// If it's empty, return badRequest()
}

return transaction.flatMap { transactionRepository.save(it).then(created(URI.create("/transaction/" + it.id)).build()) }
}

有可能做我想做的事吗?

最佳答案

允许检查 Flux/Mono 是否为空的技术

使用运算符.switchIfEmpty/.defaultIfEmpty/Mono.repeatWhenEmpty

使用提到的运算符,您将能够对 Stream 已完成的情况使用react,而不会发出任何元素。

首先,请记住,.map.flatMap.filter 和许多其他操作符在以下情况下根本不会被调用没有调用 onNext。这意味着在您的情况下,下一个代码

transaction.flatMap {
val user = userRepository.findById(it.userId)
// If it's empty, return badRequest()
}

return transaction.flatMap { transactionRepository.save(it).then(created(URI.create("/transaction/" + it.id)).build()) }

根本不会被调用,如果transaction为空

如果在你的流为空的情况下需要处理case,你应该考虑像next这样的操作符,方式如下:

transaction
.flatMap(it -> {
val user = userRepository.findById(it.userId)
})
.swithIfEmpty(Flux.defer(() -> Flux.just(badRequest())));

实际解决方案

另外,我注意到您从主 transaction 创建了两个子流程。实际上,下面的代码根本不会被执行:

transaction.flatMap {
val user = userRepository.findById(it.userId)
// If it's empty, return badRequest()
}

并且只会执行最后一个,它是从方法返回的。发生这种情况是因为您没有使用运算符 .subscribe(...).

订阅

第二点,你不能一次订阅同一个请求体(WebClient的响应的一种限制)。因此,您需要以下一种方式分享您的请求正文,因此完成的示例将是:

fun createTransaction(serverRequest: ServerRequest): Mono<ServerResponse> {
val transaction = serverRequest.body(BodyExtractors.toMono(Transaction::class.java)).cache()

transaction
.flatMap { userRepository.findById(it.userId) }
.flatMap { transaction.flatMap { transactionRepository.save(it) } }
.flatMap { ServerResponse.created(URI.create("/transaction/" + it.id)).build() }
.switchIfEmpty(transaction.flatMap { ServerResponse.badRequest().syncBody("missed User for transaction " + it.id) })
}

或者更简单的情况,不共享事务流但使用Tuple:

fun createTransaction(serverRequest: ServerRequest): Mono<ServerResponse> {
val emptyUser = !User()
val transaction = serverRequest.body<Mono<Transaction>>(BodyExtractors.toMono(Transaction::class.java))

transaction
.flatMap { t ->
userRepository.findById(t.userId)
.map { Tuples.of(t, it) }
.defaultIfEmpty(Tuples.of(t, emptyUser))
}
.flatMap {
if (it.t2 != emptyUser) {
transactionRepository.save(it.t1)
.flatMap { ServerResponse.created(URI.create("/transaction/" + it.id)).build() }
} else {
ServerResponse.badRequest().syncBody("missed User for transaction " + it.t1.id)
}
}
}

关于spring - 如何检查 Mono 是否为空?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47242335/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com