0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

RestTemplateではなくRestClientを使う

Posted at

RestTemplateに対するSpring公式の見解

以下、2025年9月30日時点のブログから引用です。

これは「Road to GA」シリーズの新しいブログ記事です。今回は Spring の HTTP クライアントに追加された新機能を紹介します。同時に、このタイミングで Spring における HTTP クライアントの全体像を振り返るのにも良い機会なので、重要なお知らせも合わせてお伝えします:私たちは RestTemplate を公式に非推奨にします。

公式としての、上記の理由は以下

まず「テンプレート型(template-style)のAPI」は、機能の範囲が限られている間は便利ですが、新機能をどんどん追加していくと途端に苦しくなります。

RestTemplate の Javadoc には大量のオーバーロードが並んでおり、IDE の補完にもずらっと出てきます。
新しい機能を導入しようとするたびに、開発者体験が犠牲になるのです。

まとめると、RestTemplate はとても人気がある一方で、その「テンプレート型API」は限界に達しており、完全な作り直しが必要なレベルまで来てしまっていました。

Spring公式からは、以下述べられています。

  • RestTemplateではAPIバージョニングを行う場合、コンストラクタを追加しなければならない
  • テンプレート型APIでは非同期呼び出しを行う場合、下層のHTTPリソースを効率良く扱えない
  • RestTemplateの使い方はレスポンス全体を一気に受け取り変換し、閉じることであり、昨今一般的なSSEが扱いづらい

すなわち、Springの今後ではテンプレート型APIは限界に達しているため、今後RestTemplateではなく、RestClientを使っていこうということです。

引用:https://spring.io/blog/2025/09/30/the-state-of-http-clients-in-spring

それではRestTemplateからどのようにRestClientに変換するか

シチュエーションとして、マイクロサービスアプリケーションでユーザー取得サービスからユーザー情報取得サービスへの通信を例とします。

RestTemplate版

1. クライアントクラス

@Component
public class UserInfoClient {

    private final RestTemplate restTemplate;
    private static final String BASE_URL = "https://userinfo.com";

    public UserInfoClient(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    public UserInfoResponse getUserInfo(UserRequest request) {
        String url = baseUrl + "/infos";
        // postForObjectでJSONボディを送信し、結果を受け取る
        return restTemplate.postForObject(url, request, UserInfoResponse.class);
    }
}

2. 設定クラス

@Configuration
public class RestTemplateConfig {
    @Bean
    public RestTemplate restTemplate() {
        // 下層HTTPクライアント設定
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        // TCPコネクション確立タイムアウト値
        factory.setConnectTimeout(3000); // 3秒
        // レスポンス受信タイムアウト値
        factory.setReadTimeout(5000);    // 5秒
        return new RestTemplate(factory);
    }
}

RestClient版

1. クライアントクラス

import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClient;

@Component
public class UserInfoClient {

    private final RestClient restClient;
    private static final String BASE_URL = "https://userinfo.com";

    // org.springframework.web.client.RestClientを使用する
    public UserInfoClient(RestClient restClient) {
        this.restClient = restClient;
    }

    public UserInfoResponse getUserInfo(UserRequest request) {
        return restClient
                .post()
                .uri(BASE_URL + "/infos")
                .body(request) // JSONにシリアライズされる
                .retrieve()
                .body(UserInfoResponse.class);
    }
}

2. 設定クラス

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestClient;

@Configuration
public class RestClientConfig {

    @Bean
    public RestClient restClient() {
        // RestClient自体はBuilderパターンなので、下層のHTTP設定を組み込んで返す
        return RestClient
                .builder()
                .requestFactory(this.clientHttpRequestFactory())
                .build();
    }

    @Bean
    public ClientHttpRequestFactory clientHttpRequestFactory() {
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        // TCPコネクション確立タイムアウト値
        factory.setConnectTimeout(3000); // 3秒
        // レスポンス受信タイムアウト値
        factory.setReadTimeout(5000);    // 5秒
        return factory;
    }
}

両者の比較

RestTemplateとRestClientで比較したときにポイントとなるメソッドはretrieve()メソッドです。
このメソッドはちょうどリクエストに対して、レスポンスの取得を意味するメソッドです。
RestTemplateのpostForObjectを三分割した形となります。

また、retrieve()の代わりにexchange()を使用すれば、より自由度が増します。

import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClient;

@Component
public class UserInfoClient {

    private final RestClient restClient;
    private static final String BASE_URL = "https://userinfo.com";

    public UserInfoClient(RestClient restClient) {
        this.restClient = restClient;
    }

    public UserInfoResponse getUserInfo(UserRequest request) {
        return restClient
                .post()
                .uri(BASE_URL + "/infos")
                .body(request)
                .exchange((clientRequest, clientResponse) -> {
                    // clientRequestを使用すれば、実際のリクエスト内容を確認できる
                    // clientResponseを使用すれば、ヘッダやペイロードのロギングも可能
                    
                    // レスポンスボディ(JSON)をUserInfoResponseに変換して返す
                    return clientResponse.bodyTo(UserInfoResponse.class);
                });
    }
}

まとめ

このように、RestTemplateからRestClientへの修正自体はかなり容易に行えます。
また、RestTemplateにはなかった柔軟な設定やコールバック処理も魅力ですね。

RestTemplateからRestClientへの移行(メソッドマッピング)は以下をご参照ください。
https://spring.pleiades.io/spring-framework/reference/integration/rest-clients.html#_migrating_from_resttemplate_to_restclient

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?