Mono가 비어있는지 확인하는 방법은?
저는 웹 플럭스 프레임워크를 이용하여 스프링부트 2.0과 코틀린이 적용된 앱을 개발하고 있습니다.
트랜잭션을 저장하기 전에 사용자 ID가 종료되는지 확인하고 싶습니다.모노가 비어있는지 확인하는 것 같은 간단한 일에 갇혀있습니다.
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이 완료되었을 때 어떠한 요소도 방출하지 않고 대응할 수 있습니다.
우선, 운영자들은 다음과 같은.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
.flatMap(it -> {
val user = userRepository.findById(it.userId)
})
.swithIfEmpty(Flux.defer(() -> Flux.just(badRequest())));
실해
또한 메인에서 2개의 서브 플로우를 생성한 것에 주목했습니다.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)
}
}
}
Mono에서 제공하는 메서드 hasElement()를 사용하여 확인할 수 있으며, 이는 Optional의 isPresent()와 유사합니다.메소드 정의는 다음과 같습니다.
Mono<Boolean> hasElement()
자세한 사항 확인 : 프로젝트 원자로 문서
이 값을 기준으로 일부 작업을 수행해야 하는 경우 switchIfEmpty()를 사용하여 대체 게시자를 제공할 수 있습니다.
먼저 저는 반응형(자바)과 이 포럼에 대해 초보자라고 말씀드리겠습니다.모노가 나중에 실행될 코드를 나타내기 때문에 모노가 비어 있으면 이 코드를 체크인할 수 없다고 생각합니다. 그래서 이 코드 본문에서는 아직 비어 있는지 여부를 알 수 없습니다.이해 하셨나요?
저는 방금 자바에서 작동하는 것처럼 보이는 비슷한 것을 썼습니다. (그러나 100% 이것이 최선의 접근법은 아닙니다.)
public Mono<ServerResponse> queryStore(ServerRequest request) {
Optional<String> postalCode = request.queryParam("postalCode");
Mono<ServerResponse> badQuery = ServerResponse.badRequest().build();
Mono<ServerResponse> notFound = ServerResponse.notFound().build();
if (!postalCode.isPresent()) { return badQuery; }
Flux<Store> stores = this.repository
.getNearByStores(postalCode.get(), 5);
return ServerResponse.ok().contentType(APPLICATION_JSON)
.body(stores, Store.class)
.switchIfEmpty(notFound);
}
옵션과 함께 Mono 사용:
return findExistingUserMono
.map(Optional::of)
.defaultIfEmpty(Optional.empty())
.flatMap(optionalUser -> {
if(optionalUser.isPresent()) {
return Mono.error('xxxx');
}
return this.userService.create(optionalUser.get());
});
이렇게 하면 스트림이 끊어지지 않도록 항상 Optional 값을 내보냅니다.
switchIfEmpty 메서드를 사용할 수 있습니다.
아래 예제에서는 사용자가 이메일과 함께 존재하는지 확인한 후 추가합니다.
userRepository.findByEmail(user.getEmail())
.switchIfEmpty(s -> {
user.setStatus("InActive");
String encodedPassword = DigestUtils.sha256Hex(user.getPassword());
user.setPassword(encodedPassword);
userRepository.save(user).subscribe();
s.onComplete();
}).then(Mono.just(user));
언급URL : https://stackoverflow.com/questions/47242335/how-to-check-if-mono-is-empty
'source' 카테고리의 다른 글
Dectrine DBAL - WHERE IN 배열에 추가 매개변수 포함 (0) | 2023.10.17 |
---|---|
자바스크립트로 작성된 C 인터프리터 (0) | 2023.10.17 |
JS를 사용하여 이름 이니셜 가져오기 (0) | 2023.10.17 |
C의 함수 내부의 함수 (0) | 2023.10.17 |
공백 문자를 모두 바꿉니다. (0) | 2023.10.17 |