Spring Web Reactive | 2. WebClient | 2.8. Synchronous Use

最後に結果をブロックすることで、WebClientを同期スタイルで使用できます。

Java

Person person = client.get().uri("/person/{id}", i).retrieve()
    .bodyToMono(Person.class)
    .block();

List<Person> persons = client.get().uri("/persons").retrieve()
    .bodyToFlux(Person.class)
    .collectList()
    .block();

Kotlin

val person = runBlocking {
    client.get().uri("/person/{id}", i).retrieve()
            .awaitBody<Person>()
}

val persons = runBlocking {
    client.get().uri("/persons").retrieve()
            .bodyToFlow<Person>()
            .toList()
}

ただし、複数回呼び出す必要がある場合は、各レスポンスを個別にブロックせず、結合した結果を待つ方が効率的です。

Java

Mono<Person> personMono = client.get().uri("/person/{id}", personId)
        .retrieve().bodyToMono(Person.class);

Mono<List<Hobby>> hobbiesMono = client.get().uri("/person/{id}/hobbies", personId)
        .retrieve().bodyToFlux(Hobby.class).collectList();

Map<String, Object> data = Mono.zip(personMono, hobbiesMono, (person, hobbies) -> {
            Map<String, String> map = new LinkedHashMap<>();
            map.put("person", person);
            map.put("hobbies", hobbies);
            return map;
        })
        .block();

Kotlin

val data = runBlocking {
        val personDeferred = async {
            client.get().uri("/person/{id}", personId)
                    .retrieve().awaitBody<Person>()
        }

        val hobbiesDeferred = async {
            client.get().uri("/person/{id}/hobbies", personId)
                    .retrieve().bodyToFlow<Hobby>().toList()
        }

        mapOf("person" to personDeferred.await(), "hobbies" to hobbiesDeferred.await())
    }

これらは単純な例です。複数のリモート呼び出しを行うリアクティブパイプラインを構成するためのパターンや演算子はほかにも多数あります。

FluxMonoを使用する場合、Spring MVCまたはSpring WebFluxのコントローラーでブロックする必要はありません。コントローラーメソッドからリアクティブ型を返すだけです。同じ原則はKotlinコルーチンとSpring WebFluxにも適用されます。コントローラーメソッドで中断関数を使用するか、Flowを返します。