0개 또는 1개의 결과를 비동기로 처리하는 리액티브 타입. 단건을 조회하거나 저장하는데 사용한다.
// 값 있는 Mono
Mono<String> mono = Mono.just("hello");
// 빈 Mono (0개)
Mono<String> empty = Mono.empty();
// 에러 Mono
Mono<String> error = Mono.error(new RuntimeException("에러"));
// 지연 실행
Mono<String> defer = Mono.defer(() -> Mono.just("lazy"));
주요 메서드는 다음과 같다.
// 값 변환
Mono.just("hello")
.map(s -> s.toUpperCase()); // HELLO
// 비동기 변환 (Mono 반환하는 함수)
Mono.just(1)
.flatMap(id -> findUserById(id)); // Mono<User>
// 값 없을 때 기본값
Mono.empty()
.defaultIfEmpty("기본값");
// 에러 처리
Mono.error(new RuntimeException())
.onErrorReturn("fallback");
// 값 소비 (사이드 이펙트)
Mono.just("hello")
.doOnNext(s -> log.info(s));
하나의 Mono 객체는 는 구독하지 않으면 그 전까지는 실행되지 않는다. 레이지하게 반응함.
mono.subscribe(
value -> System.out.println("값: " + value), // onNext
error -> System.out.println("에러: " + error), // onError
() -> System.out.println("완료") // onComplete
);
하지만 WebFlux 컨트롤러에서 사용하면 직접 구독하지 않고 반환만 해도 프레임워크가 알아서 처리한다.
@RestController
public class UserController {
@GetMapping("/user/{id}")
public Mono<User> getUser(@PathVariable Long id) {
return userService.findById(id); // 구독은 WebFlux가 처리
}
@PostMapping("/user")
public Mono<ResponseEntity<User>> createUser(@RequestBody Mono<User> body) {
return body
.flatMap(userService::save)
.map(user -> ResponseEntity.ok(user));
}
}
0~N개의 데이터를 비동기적으로 처리하는 리액티브 타입. 쉽게 말하면 스트림임
WebFlux에서 HTTP 응답은 항상 Mono 이지만, 그 내부 Body는 Flux 일 수 있다.
다음과 같이 생성한다.
// 고정된 값
Flux.just("a", "b", "c")
// 컬렉션으로부터
Flux.fromIterable(listOf(1, 2, 3))
// 범위
Flux.range(1, 5) // 1, 2, 3, 4, 5
// 빈 Flux
Flux.empty()
// 에러
Flux.error(RuntimeException("에러"))
// 무한 스트림
Flux.interval(Duration.ofSeconds(1)) // 1초마다 값 발행