はじめに
前回の記事では、WebClient
を使ってOpenWeatherMap APIに非同期でアクセスする方法をご紹介しました。
今回はその続編として、より深くリアクティブプログラミングの基礎であるMono
とFlux
、エラーハンドリングの実践例、そして非推奨ながらblockする方法について解説します。
MonoとFluxとは?
WebClient
はSpring WebFluxのリアクティブな仕組みの上で動作します。その中核となるのが以下の2つの型:
型 | 意味 | 用途例 |
---|---|---|
Mono<T> |
0個または1個のデータを非同期に返す | APIの単一レスポンスなど |
Flux<T> |
0個以上のデータ(ストリーム)を非同期に返す | リアルタイムログ、ストリーミングデータなど |
Monoの例(天気情報1件)
Mono<WeatherResponse> response = webClient.get()
.uri("/weather?...") // パラメータ略
.retrieve()
.bodyToMono(WeatherResponse.class);
Fluxの例(複数データをストリームで受け取る)
Flux<String> stream = Flux.just("晴れ", "曇り", "雨");
エラーハンドリングの書き方
API通信は常に成功するとは限りません。WebClient
では、onStatus()
などを用いてHTTPステータスごとのエラー処理が可能です。
実例:404などのエラー対応
public Mono<WeatherResponse> getWeather(String city) {
return webClient.get()
.uri(uriBuilder -> uriBuilder
.path("/weather")
.queryParam("q", city)
.queryParam("appid", apiKey)
.queryParam("units", "metric")
.build())
.retrieve()
.onStatus(HttpStatus::is4xxClientError, response -> {
return Mono.error(new RuntimeException("クライアントエラー(都市名などを確認)"));
})
.onStatus(HttpStatus::is5xxServerError, response -> {
return Mono.error(new RuntimeException("サーバーエラー"));
})
.bodyToMono(WeatherResponse.class);
}
.doOnError()
.doOnError(e -> log.error("API呼び出し中にエラー:{}", e.getMessage()))
非推奨:block()で同期的に取得する方法
非同期処理が基本ですが、「どうしても今ここで値を取り出したい」という場合はblock()
を使うこともできます。ただしスレッドをブロックするため推奨されません。
使用例(同期取得)
WeatherResponse response = webClient.get()
.uri("/weather?...") // パラメータ略
.retrieve()
.bodyToMono(WeatherResponse.class)
.block(); // ★同期的に取得(注意)
注意:WebFluxの世界ではなるべく
block()
を使わずに全体をリアクティブに設計するのがベストです。
まとめ
-
Mono
:1件の非同期データ、Flux
:複数件のストリームデータ -
WebClient
でのエラーハンドリングはonStatus()
やdoOnError()
を活用 -
block()
を使用する際は設計の見直しも含めて検討する