RestTemplateを使ったAPI呼び出しをする(Spring Boot)

依存関係の追加

build.gradleに以下の依存関係を追加する。 SpringBootと同じバージョンを使用するため、バージョンの記述は不要。

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
}



RestTemplateのインスタンスを作成する

コンストラクタで作成する

RestTemplateには以下の3つのコンストラクタが用意されている。

コンストラクタ 説明
RestTemplate() デフォルト設定を使用して、RestTemplate の新しいインスタンスを作成する。
RestTemplate(ClientHttpRequestFactory requestFactory) 指定された ClientHttpRequestFactory に基づいて、RestTemplate の新しいインスタンスを作成する。
RestTemplate(List<HttpMessageConverter<?>> messageConverters) HttpMessageConverter のリストを使用して、RestTemplate の新しいインスタンスを作成する

RestTemplate()

特に独自の設定を行わない場合に使用する。

public void doSomething(){
    RestTemplate template = new ResuTemplate();
}

RestTemplate(ClientHttpRequestFactory requestFactory)

特にClientHttpRequestFactoryを指定しない場合はorg.springframework.http.client.SimpleClientHttpRequestFactoryが使用される。
上記のデフォルトで使用されるクラスではコネクションタイムアウトの設定などができる。
タイムアウトのデフォルト値はシステムのデフォルトのタイムアウト値のため、RestTemplateで別のタイムアウト値を指定したい場合などに使用する。

public void doSomething(){
    SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
    factory.setConnectTimeout(3000); // ミリ秒で指定
    RestTemplate template = new ResuTemplate(factory);
}

SimpleClientHttpRequestFactoryクラスで設定できる値などについては、公式のJavadoc参照。

RestTemplate(List<HttpMessageConverter<?>> messageConverters)

独自のメッセージコンバータを作成していて、それを使用したい場合はこのコンストラクタで指定する。
メッセージコンバータは、アプリケーションで扱うJavaオブジェクトとJSON等を相互に変換するためのインタフェースであり、RestTemplateではデフォルトでいくつか設定されている。(参照)
※このメソッドで設定を上書きした場合は元々設定されていたものは削除されるので注意する。

RestTemplateBuilderを使用する

コンストラクタではあまり細かい設定ができないため、細かい設定を行いたい場合や複数の設定を行いたい場合はRestTemplateBuilderを使用する。
RestTemplateBuilderはDIコンテナから取得することができる。

public class SampleHttpClient {
    // コンストラクタインジェクションで取得
    public SampleHttpClient(RestTemplateBuilder builder){
        RestTemplate template = builder.build();
    }
}

RestTemplateBuilderに用意されているメソッドには下記のものがある。

メソッド名 引数 説明
additionalCustomizers Collection<? extends RestTemplateCustomizer> customizers RestTemplateCustomizersを追加する
additionalCustomizers RestTemplateCustomizer… customizers RestTemplateCustomizersを追加する
additionalInterceptors Collection<? extends ClientHttpRequestInterceptor> interceptors ClientHttpRequestInterceptorsを追加する
additionalInterceptors ClientHttpRequestInterceptor… interceptors ClientHttpRequestInterceptorsを追加する
additionalMessageConverters Collection<? extends HttpMessageConverter<?>> messageConverters HttpMessageConvertersを追加する
additionalMessageConverters HttpMessageConverter<?>... messageConverters HttpMessageConvertersを追加する
additionalRequestCustomizers Collection<? extends RestTemplateRequestCustomizer<?>> requestCustomizers RestTemplateRequestCustomizersを追加する
additionalRequestCustomizers RestTemplateRequestCustomizer<?>... requestCustomizers RestTemplateRequestCustomizersを追加する
basicAuthentication String username
String password
指定されたユーザー名/パスワードのペアを持つリクエストにHTTP基本認証を追加する
basicAuthentication String username
String password
Charset charset
指定されたユーザー名/パスワードのペアを持つリクエストにHTTP基本認証を追加する
customizers Collection<? extends RestTemplateCustomizer> customizers RestTemplateCustomizersを設定する
customizers RestTemplateCustomizer… customizers RestTemplateCustomizersを設定する
defaultHeader String name
String… values
デフォルトヘッダーを設定する
defaultMessageConverters なし RestTemplateデフォルトのHttpMessageConvertersを設定する
detectRequestFactory boolean detectRequestFactory ClientHttpRequestFactory をクラスパスに基づいて検出する必要がある場合trueを設定する
errorHandler ResponseErrorHandler errorHandler ResponseErrorHandlerを設定する
interceptors ClientHttpRequestInterceptor… interceptors ClientHttpRequestInterceptorsを設定する
interceptors Collection<ClientHttpRequestInterceptor> interceptors ClientHttpRequestInterceptorsを設定する
messageConverters Collection<? extends HttpMessageConverter<?>> messageConverters HttpMessageConvertersを設定する
messageConverters HttpMessageConverter<?>... messageConverters HttpMessageConvertersを設定する
requestCustomizers Collection<? extends RestTemplateRequestCustomizer<?>> requestCustomizers RestTemplateRequestCustomizersを設定する
requestCustomizers RestTemplateRequestCustomizer<?>... requestCustomizers RestTemplateRequestCustomizersを設定する
requestFactory Class<? extends ClientHttpRequestFactory> requestFactory ClientHttpRequestFactoryクラスを設定する
requestFactory Supplier<ClientHttpRequestFactory> requestFactory ClientHttpRequestFactoryのSupplierを設定する
rootUri String rootUri ‘/’ で始まる各リクエストに適用されるルート URL を設定する
setBufferRequestBody boolean bufferRequestBody ClientHttpRequestFactoryがリクエスト本文を内部的にバッファリングする必要があるかどうかを設定する
setConnectTimeout Duration connectTimeout コネクションタイムアウトを設定する
setReadTimeout Duration readTimeout 読み取りタイムアウトを設定する
uriTemplateHandler UriTemplateHandler uriTemplateHandler UriTemplateHandler を設定する



RestTemplateでリクエストを送信する

RestTemplateには各種HTTPメソッドのリクエストを送るためのメソッドが用意されている。

GET

戻り値 メソッド名 引数の型 引数名 引数の説明
ResponseEntity<T> getForEntity String
Class<T>
Object…
url
responseType
uriVariables
URL
レスポンスボディの型
URLの埋め込み文字
ResponseEntity<T> getForEntity String
Class<T>
Map<String, ?>
url
responseType
uriVariables
URL
レスポンスボディの型
URLの埋め込み文字
ResponseEntity<T> getForEntity URI
Class<T>
url
responseType
URL
レスポンスボディの型
T getForObject String
Class<T>
Object…
url
responseType
uriVariables
URL
レスポンスボディの型
URLの埋め込み文字
T getForObject String
Class<T>
Map<String, ?>
url
responseType
uriVariables
URL
レスポンスボディの型
URLの埋め込み文字
T getForObject URI
Class<T>
url
responseType
URL
レスポンスボディの型

DELETE

戻り値 メソッド名 引数の型 引数名 引数の説明
void delete String
Object…
url
uriVariables
URL
URLの埋め込み文字
void delete String
Map<String, ?>
url
uriVariables
URL
URLの埋め込み文字
void delete URI url URL

PUT

戻り値 メソッド名 引数の型 引数名 引数の説明
void put String
Object
Object…
url
request
uriVariables
URL
リクエストボディ
URLの埋め込み文字
void put String
Object
Map<String, ?>
url
request
uriVariables
URL
リクエストボディ
URLの埋め込み文字
void put URI
Object
url
request
URL
リクエストボディ

POST

戻り値 メソッド名 引数の型 引数名 引数の説明
ResponseEntity<T> postForEntity String
Object
Class<T>
Object…
url
request
responseType
uriVariables
URL
リクエストボディ
レスポンスボディの型
URLの埋め込み文字
ResponseEntity<T> postForEntity String
Object
Class<T>
Map<String, ?>
url
request
responseType
uriVariables
URL
リクエストボディ
レスポンスボディの型
URLの埋め込み文字
ResponseEntity<T> postForEntity URI
Object
Class<T>
url
request
responseType
URL
リクエストボディ
レスポンスボディの型
T postForObject String
Object
Class<T>
Object…
url
request
responseType
uriVariables
URL
リクエストボディ
レスポンスボディの型
URLの埋め込み文字
T postForObject String
Object
Class<T>
Map<String, ?>
url
request
responseType
uriVariables
URL
リクエストボディ
レスポンスボディの型
URLの埋め込み文字
T postForObject URI
Object
Class<T>
url
request
responseType
URL
リクエストボディ
レスポンスボディの型
URI postForLocation String
Object
Object…
url
request
uriVariables
URL
リクエストボディ
URLの埋め込み文字
URI postForLocation String
Object
Map<String, ?>
url
request
uriVariables
URL
リクエストボディ
URLの埋め込み文字
URI postForLocation URI
Object
url
request
URL
リクエストボディ
戻り値 メソッド名 引数の型 引数名 引数の説明
HttpHeaders headForHeaders String
Object…
url
uriVariables
URL
URLの埋め込み文字
HttpHeaders headForHeaders String
Map<String, ?>
url
uriVariables
URL
URLの埋め込み文字
HttpHeaders headForHeaders URI url URL

PATCH

戻り値 メソッド名 引数の型 引数名 引数の説明
T patchForObject String
Object
Class<T>
Object…
url
request
responseType
uriVariables
URL
リクエストボディ
レスポンスボディの型
URLの埋め込み文字
T patchForObject String
Object
Class<T>
Map<String, ?>
url
request
responseType
uriVariables
URL
リクエストボディ
レスポンスボディの型
URLの埋め込み文字
T patchForObject URI
Object
Class<T>
url
request
responseType
URL
リクエストボディ
レスポンスボディの型

OPTIONS

戻り値 メソッド名 引数の型 引数名 引数の説明
Set<HttpMethod> optionsForAllow String
Object…
url
uriVariables
URL
URLの埋め込み文字
Set<HttpMethod> optionsForAllow String
Map<String, ?>
url
uriVariables
URL
URLの埋め込み文字
Set<HttpMethod> optionsForAllow URI url URL

汎用

リクエストヘッダを使用したい場合などは汎用的なこのメソッドを使用する。

ParameterizedTypeReference
レスポンスボディをリストやマップなど総称型を伴うクラスにマッピングしたい場合に使用する。

ResponseEntity<List<Todo>> responseEntity =    restTemplate.exchange(requestEntity, new ParameterizedTypeReference<List<MyClass>>() {});

org.springframework.http.HttpEntity<T>
リクエストのヘッダー・ボディを格納するクラス。

HttpEntity entity = new HttpEntity<Object>(requestBody, headers)


戻り値 メソッド名 引数の型 引数名 引数の説明
ResponseEntity<T> exchange String
HttpMethod
HttpEntity<?>
Class<T>
Object…
url
method
requestEntity
responseType
uriVariables
URL
HTTPメソッド
リクエスト
レスポンスボディの型
URLの埋め込み文字
ResponseEntity<T> exchange String
HttpMethod
HttpEntity<?>
Class<T>
Map<String, ?>
url
method
requestEntity
responseType
uriVariables
URL
HTTPメソッド
リクエスト
レスポンスボディの型
URLの埋め込み文字
ResponseEntity<T> exchange String
HttpMethod
HttpEntity<?>
Class<T>
url
method
requestEntity
responseType
URL
HTTPメソッド
リクエスト
レスポンスボディの型
ResponseEntity<T> exchange String
HttpMethod
HttpEntity<?>
ParameterizedTypeReference<T>
Object…
url
method
requestEntity
responseType
uriVariables
URL
HTTPメソッド
リクエスト
レスポンスボディの型
URLの埋め込み文字
ResponseEntity<T> exchange String
HttpMethod
HttpEntity<?>
ParameterizedTypeReference<T>
Map<String, ?>
url
method
requestEntity
responseType
uriVariables
URL
HTTPメソッド
リクエスト
レスポンスボディの型
URLの埋め込み文字
ResponseEntity<T> exchange String
HttpMethod
HttpEntity<?>
ParameterizedTypeReference<T>
url
method
requestEntity
responseType
URL
HTTPメソッド
リクエスト
レスポンスボディの型
ResponseEntity<T> exchange HttpEntity<?>
Class<T>
requestEntity
responseType
リクエスト
レスポンスボディの型
ResponseEntity<T> exchange HttpEntity<?>
ParameterizedTypeReference<T>
requestEntity
responseType
リクエスト
レスポンスボディの型

その他設定系メソッド

// 設定されているメッセージコンバーターと照合して、引数で受け取ったレスポンスボディの型に基づいて
// リクエストにAcceptヘッダーを設定するRequestCallbackを返す
RequestCallback acceptHeaderRequestCallback(Class<T> responseType)

// 引数で受け取ったリクエストボディをリクエストストリームに書き込むRequestCallbackを返す
RequestCallback httpEntityCallback(@Nullable Object requestBody)

// 以下を満たすRequestCallbackを返す
// ・設定されているメッセージコンバーターと照合して、引数で受け取ったレスポンスボディの型に基づいてリクエストにAcceptヘッダーを設定する
// ・引数で受け取ったリクエストボディをリクエストストリームに書き込む
RequestCallback httpEntityCallback(@Nullable Object requestBody, Type responseType)

// ResponseEntity を準備する ResponseExtractor を返す
ResponseExtractor<ResponseEntity<T>> responseEntityExtractor(Type responseType)

// URLの埋め込み文字のデフォルト値を設定する。
void setDefaultUriVariables(Map<String, ?> uriVars)

// エラーハンドラーを設定する
// デフォルト:org.springframework.web.client.DefaultResponseErrorHandler
void setErrorHandler(ResponseErrorHandler errorHandler)

// 使用するメッセージボディコンバータを設定する
// これらのコンバーターは、HTTPリクエストおよびレスポンスの変換に使用される
void setMessageConverters(List<HttpMessageConverter<?>> messageConverters)

// URI テンプレートを展開するためのハンドラーを設定する
// デフォルト:org.springframework.web.util.DefaultUriBuilderFactory
void setUriTemplateHandler(UriTemplateHandler handler)

// 現在RestTemplateに設定されているエラーハンドラやメッセージコンバータ等を取得するためのメソッドたち
ResponseErrorHandler getErrorHandler()
List<HttpMessageConverter<?>> getMessageConverters()
UriTemplateHandler getUriTemplateHandler()

リトライ処理の実装

Spring-retryを使用して実装を行う。

依存関係の追加

build.gradleに以下の依存関係を追加する。 バージョンの記述は不要。

dependencies {
    implementation 'org.springframework.retry:spring-retry'
    implementation 'org.springframework.boot:spring-boot-starter-aop'
}

RetryTemplateのインスタンスを作成する

コンストラクタで作成する方法とRetryTemplateBuilderで作成とがある。
RestTemplateの時と同様で、より細かい設定を行いたい場合はRetryTemplateBuilderでインスタンスを生成するとよい。

コンストラクタで作成

RetryTemplate retryTemplate = new RetryTemplate();

// RetryPolicyの設定
// CustomRetryPolicyは独自に定義したRetryPolicy
retryTemplate.setRetryPolicy(new CustomRetryPolicy(4));

// リトライ間隔の設定
ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
backOffPolicy.setInitialInterval(Duration.ofSeconds(1).toMillis());
retryTemplate.setBackOffPolicy(backOffPolicy)

RetryTemplateBuilderで作成

// 独自定義したものを設定する場合
ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
backOffPolicy.setInitialInterval(Duration.ofSeconds(1).toMillis());

RetryTemplate retryTemplate = RetryTemplate.builder()
    .customPolicy(new CustomRetryPolicy(4))
    .customBackoff(backOffPolicy)
    .build();

// 既存のものを使用する場合
RetryTemplate retryTemplate = RetryTemplate.builder()
    // 最大リトライ回数(最初の1回もカウントされる)
    .maxAttempts(5)
    // リトライのタイムアウト時間設定(ミリ秒)
    .withinMillis(100000L)
    // リトライ間隔(固定)(ミリ秒)
    .fixedBackoff(100L)
    .build();

RetryTemplateBuilderでは以下のものが設定可能。

メソッド名 引数の型 引数名 引数の説明 説明
customBackoff BackOffPolicy backOffPolicy バックオフポリシー 独自のBackOffPolicyを設定する
customPolicy RetryPolicy policy リトライポリシー 独自のRetryPolicyを設定する
exponentialBackoff long
double
long
initialInterval
multiplier
maxInterval
最初のリトライ間隔
基数(2の場合2の累乗となる)
最大のリトライ間隔
指数バックオフポリシーの設定を行う。
exponentialBackoff long
double
long
boolean
initialInterval
multiplier
maxInterval
withRandom
最初のリトライ間隔
基数(2の場合2の累乗となる)
最大のリトライ間隔
バックオフ間隔にランダム性を追加するかどうか
指数バックオフポリシーの設定を行う。
fixedBackoff long interval リトライ間隔 リトライ間隔が固定値のバックオフポリシーの設定を行う
infiniteRetry - - - リトライ回数を無限とする
maxAttempts int maxAttempts 最大リトライ回数 最大リトライ回数を設定する
noBackoff - - - リトライ間隔を0とする
notRetryOn Class<? extends Throwable> throwable 例外クラス 引数で指定した例外クラスをリトライ対象外とする。これを設定した場合、デフォルトのExceptionクラスの例外スロー時にリトライを実施する設定が削除される
notRetryOn List<Class<? extends Throwable&g>t; throwables 例外クラスのリスト 引数で指定した例外クラスをリトライ対象外とする。これを設定した場合、デフォルトのExceptionクラスの例外スロー時にリトライを実施する設定が削除される
retryOn Class<? extends Throwable> throwable 例外クラス 引数で指定した例外クラスをリトライ対象とする。これを設定した場合、デフォルトのExceptionクラスの例外スロー時にリトライを実施する設定が削除される
retryOn List<Class<? extends Throwable>> throwables 例外クラスのリスト 引数で指定した例外クラスをリトライ対象とする。これを設定した場合、デフォルトのExceptionクラスの例外スロー時にリトライを実施する設定が削除される
traversingCauses - - - Spring Retryがメイン例外の原因を調べ、例外の原因(別の例外)がリトライ対象の例外と一致する場合にリトライするように設定する
uniformRandomBackoff long
long
minInterval
maxInterval
最小リトライ間隔
最大リトライ間隔
リトライ間隔がランダムなリトライポリシーの設定を行う
withinMillis long timeout リトライのタイムアウト時間(ミリ秒) リトライのタイムアウト時間を設定する
withListener RetryListener listener リトライリスナー リトライリスナーを追加する
withListeners List<RetryListener> listeners リトライリスナーのリスト リトライリスナーを追加する


RetryListenerとは

リトライに処理を追加するためのリスナーのインターフェース。 以下の3つのメソッドが用意されている。

  • void close(RetryContext context, RetryCallback<T,E> callback, Throwable throwable) :最後のリトライのあとに実行される
  • void onError(RetryContext context, RetryCallback<T,E> callback, Throwable throwable) :リトライが失敗するたびに実行される
  • boolean open(RetryContext context, RetryCallback<T,E> callback) :最初のリトライの前に実行される falseを返却した場合はリトライがキャンセルされる

リトライ処理の実装

RetryTemplate#executeの引数に渡した処理がリトライされる。
リトライの条件は、RetryTemplateのインスタンス生成時に指定したものとなる。

実装例

@Slf4j
public class SampleClient {

    private String baseUrl;

     /** {@link RestTemplate} */
    private RestTemplate restTemplate;

    /** {@link RetryTemplate} */
    private RetryTemplate retryTemplate;

    public SampleClient(String baseUrl, RestTemplateBuilder builder){
        this.baseUrl = baseUrl;
        this.restTemplate = builder
                .setConnectTimeout(Duration.ofSeconds(3))
                .setReadTimeout(Duration.ofSeconds(60))
                .build();
        this.retryTemplate = RetryTemplate.builder()
                .maxAttempts(5)
                .fixedBackoff(100L)
                .build();
    }

    public <T> ResponseEntity<T> sendRequest(HttpMethod method, String uri, Class<T> responseBodyClass,
            Map<String, String> queryParam, Object requestBody, HttpHeaders headers) {

        String baseUri = UriComponentsBuilder
                .fromHttpUrl(StringUtils.join(baseUrl, uri))
                .build()
                .encode()
                .toUriString();

        UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder
                .fromHttpUrl(baseUri);

        if (queryParam != null && !queryParam.isEmpty()) {
            // クエリパラメータ作成
            MultiValueMap<String, String> queryParamMap = new LinkedMultiValueMap<>();
            queryParamMap.setAll(queryParam);
            uriComponentsBuilder.queryParams(queryParamMap);
        }

        String uriString = uriComponentsBuilder.build().toUriString();
        URI requestUri = URI.create(uriString);

        try {
            ResponseEntity<T> response = this.retryTemplate.execute(context -> {

                if (0 < context.getRetryCount()) {
                    log.warn("[リトライ{}回目] リトライ理由 : {}", context.getRetryCount(),
                            context.getLastThrowable().toString());
                }

                ResponseEntity<T> innerResponse = this.restTemplate.exchange(
                        requestUri, method, new HttpEntity<Object>(requestBody, headers), responseBodyClass);

                return innerResponse;
            });
            return response;
        } catch (RestClientResponseException e) {
            throw e;
        }
    }
}