【初心者向け】Spring BootのRestTemplateを使ったREST API通信の全知識

Java


スポンサーリンク

  1. ✅ 1. REST通信とは?【初心者向けに図解イメージ付きで解説】
    1. 💡 RESTとは?
    2. 🔁 REST通信の特徴
    3. 📦 具体例:ユーザー管理のREST API
    4. 🧭 REST通信の「設計の考え方」
    5. ✅ REST通信のメリット
    6. ❗ REST通信 ≠ データベース直操作
    7. ✍️ REST通信のまとめ
  2. ✅ 2. REST通信に使う RestTemplate とは?
    1. 💡 RestTemplate とは?
      1. ✅ 特徴:
    2. 🔧 どんな場面で使うの?
    3. 📦 RestTemplateが提供する主なメソッド
    4. 🛠 RestTemplate の使い方(基本の流れ)
    5. ✅ Beanとして定義するのが一般的
    6. 🔄 RestTemplate の動作は同期処理
    7. ⚠️ 補足:RestTemplateは将来的に非推奨予定
    8. 🧾 この章のまとめ
  3. ✅ 3. RestTemplateの使い方:GET通信編【JSONデータを取得してJavaオブジェクトに変換】
    1. 🧭 やりたいこと
    2. 🧱 ① モデルクラスを作成
    3. ⚙️ ② RestTemplateのGETリクエスト実装
    4. 🧪 呼び出し側のコントローラ例
    5. ✅ 実行してみると…
    6. 🧠 さらに理解を深めるポイント
      1. 1. getForObject() の返却値
      2. 2. パラメータの使い方(URLテンプレート)
    7. 🧱 エラー処理(例外)も加えるとより実用的
    8. ✅ 3章まとめ
  4. ✅ 4. RestTemplateの使い方:POSTリクエスト編【Javaオブジェクトを送信する】
    1. 🧭 やりたいこと
    2. 🧱 ① モデルクラスを用意(GETと同じ)
    3. 🛠 ② POSTリクエストを送る方法
      1. 📌 説明:
    4. 📦 実際のAPIとのやりとり(イメージ)
      1. ➤ リクエスト:
      2. ➤ レスポンス:
    5. 📌 ヘッダーを追加したいとき
    6. 🧠 よくあるミス・注意点
    7. ✅ postForObject() vs postForEntity()
    8. ✅ 4章まとめ
  5. ✅ 5. RestTemplateの使い方:PUTとDELETE編【データの更新・削除】
    1. 🔁 PUTとDELETEってなに?
  6. 🛠 ① PUTリクエスト(データの更新)
    1. 🎯 やりたいこと:
    2. 📦 実装コード:
    3. ✅ ポイント:
  7. 🗑️ ② DELETEリクエスト(データの削除)
    1. 🎯 やりたいこと:
    2. 📦 実装コード:
    3. ✅ 注意点:
    4. ✅ PUT・DELETE実行時の例外処理(共通)
    5. ✅ よくあるエラーと対策
    6. ✅ PUT/DELETEのまとめ
  8. ✅ 6. ヘッダー・トークン付きのAPI呼び出し【認証APIとの連携方法】
    1. 🔐 認証付きAPIって?
    2. 🛠 ① ヘッダー付きでGETリクエストする方法
      1. 📦 実装例(Bearerトークン付き)
    3. 🛠 ② ヘッダー付きでPOSTリクエストを送信
    4. ✅ HttpEntityとは?
    5. 🧠 よくあるAPI認証方式とその実装方法
    6. ⚠️ よくあるミス
    7. ✅ 6章まとめ
  9. ✅ 7. RestTemplateのエラーハンドリング【安全なAPI通信のために】
    1. ❗ なぜエラーハンドリングが重要?
    2. 💥 代表的なエラー(HTTPステータスコード)
    3. 🧪 基本の try-catch パターン
    4. 🧠 捕捉:よく使う例外クラス一覧
    5. 📦 レスポンスのボディも取得したいとき
    6. ✅ 実践的な設計アイデア
      1. 📌 サービス層で例外をまとめて処理して、Controller層には流さない
    7. ✅ エラーハンドリングまとめ
  10. ✅ 8. RestTemplateと非同期処理(マルチスレッド)【複数APIを並列に叩く】
    1. 🔁 なぜ非同期処理が必要なの?
    2. ✅ 解決策:非同期(マルチスレッド)で実行する
    3. 🛠 ① Springの @Async を使った非同期実行
      1. 🔧 設定:@EnableAsync を有効化
    4. 🧩 非同期メソッドの定義
    5. 🔁 複数非同期呼び出し+全完了待ち
    6. 🧠 スレッド数の調整(スレッドプール)
      1. 🛠 スレッドプールの設定
    7. ⚠️ スレッド数を増やすとどうなる?
    8. ✅ 8章まとめ
  11. ✅ 9. WebClientへの移行方法と違い【RestTemplateの後継】
    1. 🤔 なぜWebClientが登場したの?
    2. ✅ WebClientの特徴
    3. 🛠 WebClientの使い方:基本編(GET)
    4. 🧠 補足
    5. 🛠 WebClientの使い方:POST(トークン付き)
    6. 🧠 WebClient と RestTemplate の比較
    7. ✅ RestTemplateからの移行ポイント
    8. 🔚 まとめ:いつWebClientを使うべきか?

✅ 1. REST通信とは?【初心者向けに図解イメージ付きで解説】

💡 RESTとは?

REST(REpresentational State Transfer)は、Webアプリケーションでよく使われる「通信の設計ルール(アーキテクチャスタイル)」です。

Web上で「データ(リソース)」にアクセス・操作するためのシンプルな考え方で、
たとえば:

  • 「ユーザー一覧を取得」
  • 「1件のユーザー情報を更新」
  • 「投稿を削除」

といった処理を、HTTPメソッド(GET, POSTなど)で表現します。


🔁 REST通信の特徴

特徴説明
HTTPベース通信はすべて HTTP(Webの通信)で行う
URLでリソース指定/users/1 などのURLで、操作対象のデータを表現
メソッドで操作指定GET, POST, PUT, DELETE などで操作の種類を指定
ステートレスリクエストごとに状態を持たない(1回1回が独立している)

📦 具体例:ユーザー管理のREST API

操作HTTPメソッドURLパス意味
ユーザー一覧を取得GET/usersユーザー全件取得
ユーザー詳細取得GET/users/1ID=1のユーザーを取得
新規ユーザー追加POST/usersユーザー情報を新規作成
ユーザー情報更新PUT/users/1ID=1のユーザーを更新
ユーザー削除DELETE/users/1ID=1のユーザーを削除

🧭 REST通信の「設計の考え方」

RESTの設計では、「リソース(= データの対象」」をURLで表現し、
「アクション(= どうしたいか)」をHTTPメソッドで表します。

たとえば:

GET /books/5
→ 「5番の本を取得してほしい」

DELETE /books/5
→ 「5番の本を削除してほしい」

このように、動詞はHTTPメソッドに任せて、URLは「名詞」だけにするのがREST的な設計です。


✅ REST通信のメリット

  • ✅ シンプルでわかりやすい
  • ✅ URLとメソッドで動作が直感的に理解できる
  • ✅ フロントエンド・バックエンドの役割が分かれやすい
  • ✅ HTTPの標準機能(キャッシュ・認証など)が使える

❗ REST通信 ≠ データベース直操作

「REST通信でやりとりする」といっても、直接DBにアクセスしているわけではありません。

➡ 通信の中では「JSON」などのデータ形式でやり取りし、
➡ サーバー側ではそれを使ってDBにアクセスしたり、処理を行ったりしています。


✍️ REST通信のまとめ

項目説明
基本プロトコルHTTP
表現形式JSON, XML(ほとんどはJSON)
主なメソッドGET, POST, PUT, DELETE
よく使う形式URLパス + HTTPメソッド = 操作の意味が決まる

✅ 2. REST通信に使う RestTemplate とは?


💡 RestTemplate とは?

RestTemplate は、Spring Frameworkが提供するHTTPクライアントで、Javaのコードから簡単にREST APIを呼び出すためのクラスです。

「JavaからWeb API(例:天気予報APIやユーザー情報取得APIなど)を叩きたい!」
そんなときに使えるのが RestTemplate

✅ 特徴:

  • REST APIとの同期通信(=レスポンスを待ってから次に進む)
  • HTTPの GET, POST, PUT, DELETE をサポート
  • JSONやXMLの自動マッピング(レスポンス → Javaクラス)

🔧 どんな場面で使うの?

シチュエーション
外部APIのデータを取得したい天気API、地図API、認証サービスとの連携など
別のマイクロサービスにデータを送信・取得したいSpring Bootで構成された複数のアプリ間通信
バックエンドでクライアントの代わりにリクエストを送るSlack通知API、LINE BotのWebhook返信処理など

📦 RestTemplateが提供する主なメソッド

メソッド名説明
getForObject()GETリクエストでオブジェクト取得rest.getForObject(url, Class)
postForObject()POSTリクエストで結果オブジェクト取得rest.postForObject(url, obj, Class)
put()PUTリクエストrest.put(url, obj)
delete()DELETEリクエストrest.delete(url)
exchange()HTTPメソッド・ヘッダー・ボディ全制御可rest.exchange(...)

🛠 RestTemplate の使い方(基本の流れ)

  1. RestTemplateのインスタンスを作る
  2. URLを指定してGETやPOSTなどのメソッドを呼び出す
  3. レスポンス(JSONなど)をJavaクラスにマッピング

✅ Beanとして定義するのが一般的

Spring Bootでは @Bean 定義しておくことで、他のクラスから @Autowired で使い回せます。

@Configuration
public class RestTemplateConfig {
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

🔄 RestTemplate の動作は同期処理

RestTemplate を使ったAPI通信は「同期」です。

つまり:

User user = restTemplate.getForObject(url, User.class);
// ↓ ここは、レスポンスが返ってきてから実行される
System.out.println(user.getName());
  • レスポンスを待つ
  • 次の処理はそれが終わってから
  • 並列にしたいときは @AsyncCompletableFuture を使う必要あり

⚠️ 補足:RestTemplateは将来的に非推奨予定

Springの公式では、今後は WebClient(非同期・リアクティブ対応)への移行が推奨されています。

比較項目RestTemplateWebClient
通信方式同期非同期(Reactive)
複数APIを並列に呼ぶやや難しい非同期で効率的に並列化可能
記述のシンプルさわかりやすい(初心者向け)やや複雑だが柔軟性が高い

ただし、シンプルさでは今でも RestTemplate が人気。特に小規模開発やバッチ処理では現役です!


🧾 この章のまとめ

項目説明
何ができる?JavaからREST APIを呼び出す(GET, POSTなど)
メリットシンプル・少ない記述・型安全
使う手順Bean登録 → メソッド呼び出し → レスポンスをクラスに変換
注意点同期処理のため大量アクセスには向かない、WebClientが推奨されつつある

✅ 3. RestTemplateの使い方:GET通信編【JSONデータを取得してJavaオブジェクトに変換】


🧭 やりたいこと

「外部のREST APIからデータを取得し、Javaのクラスにマッピングする」

たとえば:

https://jsonplaceholder.typicode.com/users/1

というAPIにGETリクエストを送って、以下のようなJSONデータを取得します:

{
  "id": 1,
  "name": "Leanne Graham",
  "email": "leanne@example.com"
}

🧱 ① モデルクラスを作成

まずは、上のJSONデータを受け取るためのJavaクラスを作成します。

public class User {
    private int id;
    private String name;
    private String email;

    // getter/setterを忘れずに(Lombokでも可)
    public int getId() { return id; }
    public void setId(int id) { this.id = id; }

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
}

🧩 JSONのフィールド名とJavaのフィールド名は基本的に一致させましょう

⚙️ ② RestTemplateのGETリクエスト実装

import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.beans.factory.annotation.Autowired;

@Service
public class ApiService {

    @Autowired
    private RestTemplate restTemplate;

    public User fetchUserById(int id) {
        String url = "https://jsonplaceholder.typicode.com/users/" + id;
        return restTemplate.getForObject(url, User.class);
    }
}

🧪 呼び出し側のコントローラ例

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    private final ApiService apiService;

    public UserController(ApiService apiService) {
        this.apiService = apiService;
    }

    @GetMapping("/fetch-user/{id}")
    public User getUser(@PathVariable int id) {
        return apiService.fetchUserById(id);
    }
}

✅ 実行してみると…

GET http://localhost:8080/fetch-user/1

➡ 結果として、JSONがそのまま返されます:

{
  "id": 1,
  "name": "Leanne Graham",
  "email": "leanne@example.com"
}

🧠 さらに理解を深めるポイント

1. getForObject() の返却値

  • 第二引数に指定したクラスに、自動でJSONをマッピングしてくれる
  • 内部では Jackson というライブラリが変換している

2. パラメータの使い方(URLテンプレート)

String url = "https://jsonplaceholder.typicode.com/users/{id}";
User user = restTemplate.getForObject(url, User.class, 1);

{id} の部分が 1 に置換されてアクセスされる


🧱 エラー処理(例外)も加えるとより実用的

try {
    User user = restTemplate.getForObject(url, User.class);
    return user;
} catch (HttpClientErrorException e) {
    System.out.println("クライアントエラー:" + e.getStatusCode());
} catch (ResourceAccessException e) {
    System.out.println("通信エラー:" + e.getMessage());
}

✅ 3章まとめ

ポイント説明
getForObject()GETリクエストを送ってレスポンスをJavaオブジェクトで受け取る
モデルクラスが必要JSON構造に合わせたJavaクラスを用意(フィールド名一致)
URLテンプレートも対応{}を使ってパラメータを埋め込む書き方も可能
例外処理も追加すると安全接続エラーやAPIのレスポンスエラーに備えたtry-catchを用意

✅ 4. RestTemplateの使い方:POSTリクエスト編【Javaオブジェクトを送信する】


🧭 やりたいこと

「JavaオブジェクトをAPIに送信して、登録や更新などの処理をしてもらう」

たとえば:

POST https://example.com/api/users

に対して、以下のようなユーザー情報を送信して、新規登録を行うとします👇

{
  "name": "Taro Yamada",
  "email": "taro@example.com"
}

🧱 ① モデルクラスを用意(GETと同じ)

public class User {
    private String name;
    private String email;

    // Getter/Setter
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
}

🛠 ② POSTリクエストを送る方法

public void createUser() {
    String url = "https://example.com/api/users";

    User user = new User();
    user.setName("Taro Yamada");
    user.setEmail("taro@example.com");

    // レスポンスとしてUserが返ってくる想定
    User createdUser = restTemplate.postForObject(url, user, User.class);

    System.out.println("登録成功!ID: " + createdUser.getId());
}

📌 説明:

第1引数第2引数第3引数
URL送信するオブジェクトレスポンスを受け取るクラス

📦 実際のAPIとのやりとり(イメージ)

➤ リクエスト:

POST /api/users
Content-Type: application/json

{
  "name": "Taro Yamada",
  "email": "taro@example.com"
}

➤ レスポンス:

{
  "id": 123,
  "name": "Taro Yamada",
  "email": "taro@example.com"
}

このようなレスポンスがあれば、返ってきたJSONは User クラスにマッピングされます。


📌 ヘッダーを追加したいとき

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);

HttpEntity<User> entity = new HttpEntity<>(user, headers);

ResponseEntity<User> response = restTemplate.postForEntity(url, entity, User.class);

User created = response.getBody();

🧠 よくあるミス・注意点

トラブル原因&対処
415 Unsupported Media TypeContent-Type: application/json がない
400 Bad RequestJavaオブジェクトとJSONのフィールド名が一致していない
nullが返ってくるレスポンスに何も含まれていない or 型が違う

✅ postForObject() vs postForEntity()

メソッド名特徴
postForObject()レスポンスボディだけを取得(シンプル)
postForEntity()レスポンスのステータスやヘッダーも取得可能

✅ 4章まとめ

ポイント説明
postForObject()JavaオブジェクトをPOSTして、戻り値もJavaクラスで受け取る
HttpHeaders + HttpEntityヘッダーを含めて細かく制御したいときに便利
フィールド名の一致JSONとJavaのプロパティ名が一致している必要がある

✅ 5. RestTemplateの使い方:PUTとDELETE編【データの更新・削除】


🔁 PUTとDELETEってなに?

メソッド役割
PUTデータの更新ユーザー情報の編集など
DELETEデータの削除ユーザーを削除するなど

🛠 ① PUTリクエスト(データの更新)

🎯 やりたいこと:

PUT https://example.com/api/users/1

に対して、新しいユーザー情報を送信し、既存のID=1のデータを更新。


📦 実装コード:

public void updateUser(int id) {
    String url = "https://example.com/api/users/" + id;

    User user = new User();
    user.setName("Updated Name");
    user.setEmail("updated@example.com");

    restTemplate.put(url, user);
}

✅ ポイント:

  • put() は戻り値なし(void)
  • 正常に送信されれば成功(エラーは例外で検知)
  • HttpEntityHttpHeaders でカスタムも可能

📦 ヘッダー付きのPUT:

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);

HttpEntity<User> entity = new HttpEntity<>(user, headers);

restTemplate.exchange(url, HttpMethod.PUT, entity, Void.class);

🗑️ ② DELETEリクエスト(データの削除)

🎯 やりたいこと:

DELETE https://example.com/api/users/1

に対して、ID=1のユーザーを削除。


📦 実装コード:

public void deleteUser(int id) {
    String url = "https://example.com/api/users/" + id;
    restTemplate.delete(url);
}

✅ 注意点:

  • 戻り値なし(void)
  • 成功時は何も返ってこない
  • 失敗(404など)は例外が発生する

✅ PUT・DELETE実行時の例外処理(共通)

try {
    restTemplate.put(url, user);  // or delete(url)
} catch (HttpClientErrorException e) {
    System.out.println("HTTPエラー: " + e.getStatusCode());
} catch (ResourceAccessException e) {
    System.out.println("通信エラー: " + e.getMessage());
}

✅ よくあるエラーと対策

現象原因と対処法
405 Method Not Allowedサーバー側が PUT や DELETE を許可していない
400 Bad Requestリクエストボディが正しくない、またはヘッダー不足
404 Not Found指定されたIDのデータが存在しない

✅ PUT/DELETEのまとめ

ポイントPUTDELETE
メソッド名restTemplate.put()restTemplate.delete()
戻り値なし(void)なし(void)
ユースケースデータの更新(ID指定)データの削除(ID指定)
ヘッダー指定が必要なときexchange() メソッドを使うexchange() メソッドを使う

✅ 6. ヘッダー・トークン付きのAPI呼び出し【認証APIとの連携方法】


🔐 認証付きAPIって?

多くのREST APIは、セキュリティのために**認証トークン(APIキーやBearerトークン)**を必要とします。

たとえば以下のような形:

GET /api/data
Authorization: Bearer xxxxxx-abcdef-12345

これを RestTemplate を使ってどう組み込むかを見ていきます。

🛠 ① ヘッダー付きでGETリクエストする方法

📦 実装例(Bearerトークン付き)

public User getUserWithAuth() {
    String url = "https://example.com/api/users/1";

    // 認証トークンの設定
    HttpHeaders headers = new HttpHeaders();
    headers.set("Authorization", "Bearer your-token-here");

    // ヘッダー込みのリクエストエンティティを作成
    HttpEntity<String> entity = new HttpEntity<>(headers);

    // exchangeを使ってGET実行
    ResponseEntity<User> response = restTemplate.exchange(
        url,
        HttpMethod.GET,
        entity,
        User.class
    );

    return response.getBody();
}

🛠 ② ヘッダー付きでPOSTリクエストを送信

public void createUserWithAuth(User user) {
    String url = "https://example.com/api/users";

    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    headers.set("Authorization", "Bearer your-token-here");

    HttpEntity<User> entity = new HttpEntity<>(user, headers);

    ResponseEntity<User> response = restTemplate.exchange(
        url,
        HttpMethod.POST,
        entity,
        User.class
    );

    System.out.println("登録成功!ID: " + response.getBody().getId());
}

✅ HttpEntityとは?

用途説明
ヘッダーを送るHttpHeaders をセットできる
ボディを送るJSONなどのデータを含められる
両方送るnew HttpEntity<>(ボディ, ヘッダー) の形式

🧠 よくあるAPI認証方式とその実装方法

認証方式ヘッダー名設定例(Javaコード)
BearerトークンAuthorizationheaders.set("Authorization", "Bearer x")
APIキーx-api-keyなどheaders.set("x-api-key", "abc123")
Basic認証Authorizationheaders.setBasicAuth("user", "pass")

⚠️ よくあるミス

現象原因と対処法
401 Unauthorizedトークンが間違っている / ヘッダー未設定
403 Forbidden権限不足(管理者でないと見れないAPIなど)
415 Unsupported Media TypeContent-Typeapplication/json でない

✅ 6章まとめ

ポイント説明
認証APIとの通信にはヘッダー追加が必要Authorization, x-api-key などを HttpHeaders に追加
HttpEntity を使ってヘッダーとボディをまとめるGET/POST/PUTすべてのリクエストで使える
exchange() メソッドが便利HTTPメソッド・ヘッダー・ボディすべてを自由にコントロール可能

✅ 7. RestTemplateのエラーハンドリング【安全なAPI通信のために】


❗ なぜエラーハンドリングが重要?

APIを呼び出す際、必ずしも成功するとは限りません。

  • 通信先が落ちている
  • 認証トークンが無効
  • パラメータが間違っている
  • サーバーからエラーが返ってくる など

こうした事態に備えて、例外(Exception)を適切に処理する必要があります。


💥 代表的なエラー(HTTPステータスコード)

ステータスコード意味原因例
400Bad Request(リクエストが不正)パラメータ不足・バリデーションエラーなど
401Unauthorized(未認証)トークンがない・間違っている
403Forbidden(アクセス拒否)権限がない、利用制限など
404Not Found(存在しない)指定したIDのデータが存在しない
500Internal Server Errorサーバー側の処理でエラー

🧪 基本の try-catch パターン

try {
    User user = restTemplate.getForObject(url, User.class);
    return user;
} catch (HttpClientErrorException e) {
    System.out.println("クライアントエラー:" + e.getStatusCode());
} catch (HttpServerErrorException e) {
    System.out.println("サーバーエラー:" + e.getStatusCode());
} catch (ResourceAccessException e) {
    System.out.println("接続エラー:" + e.getMessage());
}

🧠 捕捉:よく使う例外クラス一覧

例外クラス名対応するエラー
HttpClientErrorException4xxエラー(認証・バリデーションなど)
HttpServerErrorException5xxエラー(サーバー内部エラーなど)
ResourceAccessExceptionタイムアウト・ドメイン不通など通信系エラー
RestClientExceptionその他すべてのRestTemplateに関する例外の親クラス

📦 レスポンスのボディも取得したいとき

catch (HttpClientErrorException e) {
    System.out.println("エラー内容: " + e.getResponseBodyAsString());
}

JSONで詳細が返ってくる場合は、ログやエラーメッセージの表示に活用できます。


✅ 実践的な設計アイデア

📌 サービス層で例外をまとめて処理して、Controller層には流さない

public User safeFetchUser(int id) {
    try {
        return restTemplate.getForObject("https://api.example.com/users/" + id, User.class);
    } catch (HttpClientErrorException.NotFound e) {
        System.out.println("ユーザーが見つかりませんでした");
        return null;
    } catch (Exception e) {
        System.out.println("予期せぬエラー: " + e.getMessage());
        return null;
    }
}

✅ エラーハンドリングまとめ

ポイント説明
try-catch で例外処理を行うAPI通信でエラーが起こる前提で安全に呼び出す
例外クラスで条件分岐が可能4xx, 5xx, タイムアウトなどで処理を分けられる
エラーレスポンスも取得できるgetResponseBodyAsString() でAPIのエラーメッセージを取得

✅ 8. RestTemplateと非同期処理(マルチスレッド)【複数APIを並列に叩く】


🔁 なぜ非同期処理が必要なの?

通常、RestTemplate同期的に動作します。

つまり、リクエストのレスポンスを待ってから次の処理に進むため、複数のAPI呼び出しが直列実行になります。

🔻 例:同期処理だと…

User user = restTemplate.getForObject(url1, User.class);
Post post = restTemplate.getForObject(url2, Post.class); // userを待つ

➡ 時間がかかる


✅ 解決策:非同期(マルチスレッド)で実行する

  • 複数のAPIを同時に呼び出す
  • 処理速度を大幅に改善
  • Springでは @AsyncCompletableFuture を使って簡単に実装できる

🛠 ① Springの @Async を使った非同期実行

🔧 設定:@EnableAsync を有効化

@Configuration
@EnableAsync
public class AsyncConfig {
}

🧩 非同期メソッドの定義

@Service
public class ApiService {

    @Autowired
    private RestTemplate restTemplate;

    @Async
    public CompletableFuture<User> getUserAsync(int id) {
        String url = "https://example.com/api/users/" + id;
        User user = restTemplate.getForObject(url, User.class);
        return CompletableFuture.completedFuture(user);
    }

    @Async
    public CompletableFuture<Post> getPostAsync(int id) {
        String url = "https://example.com/api/posts/" + id;
        Post post = restTemplate.getForObject(url, Post.class);
        return CompletableFuture.completedFuture(post);
    }
}

🔁 複数非同期呼び出し+全完了待ち

@RestController
public class ApiController {

    @Autowired
    private ApiService apiService;

    @GetMapping("/parallel")
    public String callInParallel() throws Exception {
        CompletableFuture<User> userFuture = apiService.getUserAsync(1);
        CompletableFuture<Post> postFuture = apiService.getPostAsync(1);

        // 並列に実行されて、ここで全完了を待機
        CompletableFuture.allOf(userFuture, postFuture).join();

        User user = userFuture.get();
        Post post = postFuture.get();

        return "ユーザー: " + user.getName() + " / 投稿: " + post.getTitle();
    }
}

🧠 スレッド数の調整(スレッドプール)

大量のリクエストを並列処理したいときは、スレッドの数もコントロールしたくなります。

🛠 スレッドプールの設定

@Configuration
@EnableAsync
public class AsyncConfig {

    @Bean(name = "taskExecutor")
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);     // 最小スレッド数
        executor.setMaxPoolSize(10);     // 最大スレッド数
        executor.setQueueCapacity(25);   // キューの長さ
        executor.setThreadNamePrefix("ApiThread-");
        executor.initialize();
        return executor;
    }
}

そして @Async("taskExecutor") として使えばOK:

@Async("taskExecutor")
public CompletableFuture<User> getUserAsync(int id) {
    ...
}

⚠️ スレッド数を増やすとどうなる?

メリットデメリット
処理速度が上がる(並列化)CPU・メモリの負荷が高くなる
複数APIのレスポンス待ちが減るスレッド数が多すぎると逆に遅くなる
大量のユーザーアクセスに対応可適切な調整が必要

➡ 開発環境では5〜10本、商用環境では負荷テストを実施して調整するのがおすすめです。


✅ 8章まとめ

ポイント説明
RestTemplateはデフォルトで同期処理リクエストごとに待ち時間が発生
@AsyncCompletableFutureで並列化複数APIを同時に呼び出すことで高速処理が可能
スレッドプールを設定して制御可能スレッド数、キュー長、最大数などを調整
スレッド数を増やすと負荷も増加処理性能とのバランスを考慮して設定する

✅ 9. WebClientへの移行方法と違い【RestTemplateの後継】


🤔 なぜWebClientが登場したの?

RestTemplate は長年使われてきましたが、今後は新機能の追加は行われず、非推奨(deprecated)方向になっています。

そこで登場したのが、Spring WebFlux で提供される WebClient です。


✅ WebClientの特徴

項目内容
非同期通信対応標準で非同期(ノンブロッキング)処理
高速・軽量多数のAPI通信を効率よく処理できる
柔軟性が高いヘッダー、ボディ、ステータスハンドリングが細かく制御可能
Reactive Streams対応MonoFlux を使ったリアクティブ開発が可能

🛠 WebClientの使い方:基本編(GET)

WebClient webClient = WebClient.create();

User user = webClient.get()
        .uri("https://example.com/api/users/1")
        .retrieve()
        .bodyToMono(User.class)
        .block(); // ブロッキングで待機(同期的に使う)

🧠 補足

  • bodyToMono() → 1件のレスポンス(非同期で1つの値を扱う)
  • block() を使うと同期的に使えるので、RestTemplate と近い感覚

🛠 WebClientの使い方:POST(トークン付き)

User user = new User("Taro", "taro@example.com");

User response = WebClient.create()
        .post()
        .uri("https://example.com/api/users")
        .header("Authorization", "Bearer token")
        .bodyValue(user)
        .retrieve()
        .bodyToMono(User.class)
        .block();

🧠 WebClient と RestTemplate の比較

比較項目RestTemplateWebClient
処理方式同期非同期(リアクティブ)
スレッド効率低(1処理 = 1スレッド)高(ノンブロッキング)
直感的な使いやすさ初心者向き少し難しい(が柔軟)
将来的な位置付け非推奨予定今後の標準
複数APIの並列処理工夫が必要(@Asyncなど)標準で対応(Mono, Flux

✅ RestTemplateからの移行ポイント

RestTemplateでの書き方WebClientでの書き方
getForObject()get().uri().retrieve().bodyToMono().block()
postForObject()post().uri().bodyValue().retrieve().bodyToMono().block()
ヘッダー設定header() メソッドで設定可能
トークン認証Authorizationheader() で追加

🔚 まとめ:いつWebClientを使うべきか?

シチュエーションおすすめクライアント
単純なAPI通信(バッチ・少数リクエスト)RestTemplateでもOK
多数のAPIを並列・非同期で呼びたいWebClientが最適
今後の新規開発・マイクロサービスWebClientを推奨

コメント

タイトルとURLをコピーしました