最新の安定バージョンについては、Spring Framework 6.2.11 を使用してください!

REST クライアント

Spring Framework は、REST エンドポイントを呼び出すために次の選択肢を提供します。

  • WebClient - 流れるような API を備えたノンブロッキングでリアクティブなクライアント。

  • RestTemplate - テンプレートメソッド API を使用した同期クライアント。

  • HTTP インターフェース - 生成された動的プロキシ実装を備えたアノテーション付きインターフェース。

WebClient

WebClient は、HTTP リクエストを実行するためのノンブロッキングのリアクティブクライアントです。これは 5.0 で導入され、同期、非同期、ストリーミングのシナリオをサポートする RestTemplate の代替手段を提供します。

WebClient は以下をサポートします。

  • ノンブロッキング I/O。

  • Reactive Streams のバックプレッシャー。

  • より少ないハードウェアリソースで高い同時実行性。

  • Java 8 ラムダを活用する関数スタイルの流れるような API。

  • 同期および非同期の相互作用。

  • サーバーへのストリーミングまたはサーバーからのストリーミング。

詳細については、WebClient を参照してください。

RestTemplate

RestTemplate は、HTTP クライアントライブラリを介した高レベルの API を提供します。REST エンドポイントを 1 行で簡単に呼び出すことができます。オーバーロードされたメソッドの次のグループを公開します。

RestTemplate はメンテナンスモードであり、マイナーな変更とバグのリクエストのみが受け入れられます。代わりに WebClient の使用を検討してください。
表 1: RestTemplate メソッド
メソッドグループ 説明

getForObject

GET を介して表現を取得します。

getForEntity

GET を使用して ResponseEntity (つまり、ステータス、ヘッダー、本文)を取得します。

headForHeaders

HEAD を使用して、リソースのすべてのヘッダーを取得します。

postForLocation

POST を使用して新しいリソースを作成し、レスポンスから Location ヘッダーを返します。

postForObject

POST を使用して新しいリソースを作成し、レスポンスから表現を返します。

postForEntity

POST を使用して新しいリソースを作成し、レスポンスから表現を返します。

put

PUT を使用してリソースを作成または更新します。

patchForObject

PATCH を使用してリソースを更新し、レスポンスから表現を返します。JDK HttpURLConnection は PATCH をサポートしていませんが、Apache HttpComponents などはサポートしていることに注意してください。

delete

DELETE を使用して、指定された URI のリソースを削除します。

optionsForAllow

ALLOW を使用して、リソースに許可された HTTP メソッドを取得します。

exchange

必要に応じて柔軟性を高める、前述のメソッドのより一般化された(そしてあまり独自ではない)バージョン。RequestEntity (HTTP メソッド、URL、ヘッダー、本文を入力として含む)を受け入れ、ResponseEntity を返します。

これらのメソッドでは、Class の代わりに ParameterizedTypeReference を使用して、ジェネリクスでレスポンス型を指定できます。

execute

コールバックインターフェースを介したリクエストの準備とレスポンスの抽出を完全に制御して、リクエストを実行する最も一般的な方法。

初期化

デフォルトのコンストラクターは、リクエストを実行するために java.net.HttpURLConnection を使用します。ClientHttpRequestFactory の実装を使用して、別の HTTP ライブラリに切り替えることができます。現在、Apache HttpComponents と OkHttp の組み込みサポートもあります。

例: Apache HttpComponents に切り替えるには、次のようにします。

RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory());

各 ClientHttpRequestFactory は、基礎となる HTTP クライアントライブラリに固有の構成オプションを公開します。たとえば、資格情報、接続プーリング、その他の詳細などです。

HTTP リクエストの java.net 実装は、エラー(401 など)を表すレスポンスのステータスにアクセスするときに例外を発生させる可能性があることに注意してください。これが課題になる場合は、別の HTTP クライアントライブラリに切り替えてください。
RestTemplate は、メトリクスとトレースを生成するために、可観測性のためにインストルメント化できます。RestTemplate 可観測性のサポートセクションを参照してください。

URI

RestTemplate メソッドの多くは、String 変数引数として、または Map<String,String> として URI テンプレートおよび URI テンプレート変数を受け入れます。

次の例では、String 変数引数を使用しています。

String result = restTemplate.getForObject(
		"https://example.com/hotels/{hotel}/bookings/{booking}", String.class, "42", "21");

次の例では、Map<String, String> を使用しています。

Map<String, String> vars = Collections.singletonMap("hotel", "42");

String result = restTemplate.getForObject(
		"https://example.com/hotels/{hotel}/rooms/{hotel}", String.class, vars);

次の例に示すように、URI テンプレートは自動的にエンコードされることに注意してください。

restTemplate.getForObject("https://example.com/hotel list", String.class);

// Results in request to "https://example.com/hotel%20list"

RestTemplate の uriTemplateHandler プロパティを使用して、URI のエンコード方法をカスタマイズできます。または、java.net.URI を準備して、URI を受け入れる RestTemplate メソッドの 1 つに渡すことができます。

URI の操作とエンコードの詳細については、URI リンクを参照してください。

ヘッダー

次の例に示すように、exchange() メソッドを使用してリクエストヘッダーを指定できます。

String uriTemplate = "https://example.com/hotels/{hotel}";
URI uri = UriComponentsBuilder.fromUriString(uriTemplate).build(42);

RequestEntity<Void> requestEntity = RequestEntity.get(uri)
		.header("MyRequestHeader", "MyValue")
		.build();

ResponseEntity<String> response = template.exchange(requestEntity, String.class);

String responseHeader = response.getHeaders().getFirst("MyResponseHeader");
String body = response.getBody();

ResponseEntity を返す多くの RestTemplate メソッドバリアントを介してレスポンスヘッダーを取得できます。

本文

RestTemplate メソッドに渡されたオブジェクトと RestTemplate メソッドから返されたオブジェクトは、HttpMessageConverter を使用して生のコンテンツとの間で変換されます。

POST では、次の例に示すように、入力オブジェクトはリクエスト本文に直列化されます。

URI location = template.postForLocation("https://example.com/people", person);

リクエストの Content-Type ヘッダーを明示的に設定する必要はありません。ほとんどの場合、ソース Object 型に基づいて互換性のあるメッセージコンバーターを見つけることができ、選択したメッセージコンバーターはそれに応じてコンテンツ型を設定します。必要に応じて、exchange メソッドを使用して明示的に Content-Type リクエストヘッダーを提供できます。これにより、選択されるメッセージコンバーターに影響を与えます。

GET では、次の例に示すように、レスポンスの本文が出力 Object に逆直列化されます。

Person person = restTemplate.getForObject("https://example.com/people/{id}", Person.class, 42);

リクエストの Accept ヘッダーを明示的に設定する必要はありません。ほとんどの場合、予期されるレスポンス型に基づいて互換性のあるメッセージコンバーターを見つけることができます。これにより、Accept ヘッダーにデータが入力されます。必要に応じて、exchange メソッドを使用して、Accept ヘッダーを明示的に提供できます。

デフォルトでは、RestTemplate は、オプションの変換ライブラリが存在するかどうかを判断するのに役立つクラスパスチェックに応じて、すべての組み込みメッセージコンバーターを登録します。明示的に使用するようにメッセージコンバーターを設定することもできます。

メッセージ変換

spring-web モジュールには、InputStream および OutputStream を介して HTTP リクエストとレスポンスの本文を読み書きするための HttpMessageConverter 契約が含まれています。HttpMessageConverter インスタンスは、クライアント側 (たとえば、RestTemplate) とサーバー側 (たとえば、Spring MVC REST コントローラー) で使用されます。

メインメディア(MIME)型の具体的な実装はフレームワークで提供され、デフォルトでクライアント側では RestTemplate に、サーバー側では RequestMappingHandlerAdapter に登録されます(メッセージコンバーターの構成を参照)。

HttpMessageConverter の実装については、次のセクションで説明します。すべてのコンバーターで、デフォルトのメディア型が使用されますが、supportedMediaTypes Bean プロパティを設定することでそれをオーバーライドできます。次の表は、各実装について説明しています。

表 2: HttpMessageConverter の実装
MessageConverter 説明

StringHttpMessageConverter

HTTP リクエストおよびレスポンスから String インスタンスを読み書きできる HttpMessageConverter 実装。デフォルトでは、このコンバーターはすべてのテキストメディア型(text/*)をサポートし、text/plain の Content-Type で書き込みます。

FormHttpMessageConverter

HTTP リクエストとレスポンスからフォームデータを読み書きできる HttpMessageConverter 実装。デフォルトでは、このコンバーターは application/x-www-form-urlencoded メディア型の読み取りと書き込みを行います。フォームデータは MultiValueMap<String, String> から読み取られ、そこに書き込まれます。コンバーターは、MultiValueMap<String, Object> から読み取られたマルチパートデータを書き込むこともできます(読み取ることはできません)。デフォルトでは、multipart/form-data がサポートされています。Spring Framework 5.2 以降、フォームデータの書き込み用に、追加のマルチパートサブ型をサポートできます。詳細については、FormHttpMessageConverter の javadoc を参照してください。

ByteArrayHttpMessageConverter

HTTP リクエストとレスポンスからバイト配列を読み書きできる HttpMessageConverter 実装。デフォルトでは、このコンバーターはすべてのメディア型(*/*)をサポートし、application/octet-stream の Content-Type で書き込みます。supportedMediaTypes プロパティを設定し、getContentType(byte[]) をオーバーライドすることにより、これをオーバーライドできます。

MarshallingHttpMessageConverter

org.springframework.oxm パッケージから Spring の Marshaller および Unmarshaller 抽象化を使用して XML を読み書きできる HttpMessageConverter 実装。このコンバーターを使用するには、Marshaller および Unmarshaller が必要です。これらは、コンストラクターまたは Bean プロパティを介して注入できます。デフォルトでは、このコンバーターは text/xml および application/xml をサポートしています。

MappingJackson2HttpMessageConverter

Jackson の ObjectMapper を使用して JSON を読み書きできる HttpMessageConverter 実装。Jackson が提供するアノテーションを使用して、必要に応じて JSON マッピングをカスタマイズできます。さらに制御が必要な場合(特定の型に対してカスタム JSON シリアライザー / デシリアライザーを提供する必要がある場合)、ObjectMapper プロパティを介してカスタム ObjectMapper を挿入できます。デフォルトでは、このコンバーターは application/json をサポートしています。

MappingJackson2XmlHttpMessageConverter

Jackson XML [GitHub] (英語) 拡張機能の XmlMapper を使用して XML を読み書きできる HttpMessageConverter 実装。JAXB または Jackson が提供するアノテーションを使用して、必要に応じて XML マッピングをカスタマイズできます。さらに制御が必要な場合(特定の型に対してカスタム XML シリアライザー / デシリアライザーを提供する必要がある場合)、ObjectMapper プロパティを介してカスタム XmlMapper を挿入できます。デフォルトでは、このコンバーターは application/xml をサポートしています。

SourceHttpMessageConverter

HTTP リクエストおよびレスポンスから javax.xml.transform.Source を読み書きできる HttpMessageConverter 実装。DOMSourceSAXSourceStreamSource のみがサポートされています。デフォルトでは、このコンバーターは text/xml および application/xml をサポートします。

BufferedImageHttpMessageConverter

HTTP リクエストおよびレスポンスから java.awt.image.BufferedImage を読み書きできる HttpMessageConverter 実装。このコンバーターは、Java I/O API でサポートされているメディア型を読み書きします。

Jackson JSON ビュー

次の例に示すように、Jackson JSON ビュー (英語) を指定して、オブジェクトプロパティのサブセットのみを直列化できます。

MappingJacksonValue value = new MappingJacksonValue(new User("eric", "7!jd#h23"));
value.setSerializationView(User.WithoutPasswordView.class);

RequestEntity<MappingJacksonValue> requestEntity =
	RequestEntity.post(new URI("https://example.com/user")).body(value);

ResponseEntity<String> response = template.exchange(requestEntity, String.class);

マルチパート

マルチパートデータを送信するには、値がパーツコンテンツ用の Object、ファイルパーツ用の Resource、ヘッダー付きパーツコンテンツ用の HttpEntity である MultiValueMap<String, Object> を提供する必要があります。例:

MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();

parts.add("fieldPart", "fieldValue");
parts.add("filePart", new FileSystemResource("...logo.png"));
parts.add("jsonPart", new Person("Jason"));

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_XML);
parts.add("xmlPart", new HttpEntity<>(myBean, headers));

ほとんどの場合、各パーツに Content-Type を指定する必要はありません。コンテンツ型は、直列化するために選択された HttpMessageConverter に基づいて自動的に決定されます。Resource の場合は、ファイル拡張子に基づいて決定されます。必要に応じて、MediaType に HttpEntity ラッパーを明示的に提供できます。

MultiValueMap の準備ができたら、以下に示すように RestTemplate に渡すことができます。

MultiValueMap<String, Object> parts = ...;
template.postForObject("https://example.com/upload", parts, Void.class);

MultiValueMap に少なくとも 1 つの非 String 値が含まれている場合、Content-Type は FormHttpMessageConverter によって multipart/form-data に設定されます。MultiValueMap に String 値がある場合、Content-Type は application/x-www-form-urlencoded にデフォルト設定されます。必要に応じて、Content-Type を明示的に設定することもできます。

HTTP インターフェース

Spring Framework を使用すると、HTTP サービスを HTTP 交換用のアノテーション付きメソッドを備えた Java インターフェースとして定義できます。次に、このインターフェースを実装して交換を実行するプロキシを生成できます。これは、HTTP リモートアクセスを簡素化できます。これには、基盤となる HTTP クライアントの使用の詳細をラップするファサードが含まれることがよくあります。

1 つは、@HttpExchange メソッドを使用してインターフェースを宣言することです。

interface RepositoryService {

	@GetExchange("/repos/{owner}/{repo}")
	Repository getRepository(@PathVariable String owner, @PathVariable String repo);

	// more HTTP exchange methods...

}

2 つ目は、宣言された HTTP 交換を実行するプロキシを作成することです。

WebClient client = WebClient.builder().baseUrl("https://api.github.com/").build();
HttpServiceProxyFactory factory = HttpServiceProxyFactory.builder(WebClientAdapter.forClient(client)).build();

RepositoryService service = factory.createClient(RepositoryService.class);

@HttpExchange は、すべてのメソッドに適用される型レベルでサポートされています。

@HttpExchange(url = "/repos/{owner}/{repo}", accept = "application/vnd.github.v3+json")
interface RepositoryService {

	@GetExchange
	Repository getRepository(@PathVariable String owner, @PathVariable String repo);

	@PatchExchange(contentType = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
	void updateRepository(@PathVariable String owner, @PathVariable String repo,
			@RequestParam String name, @RequestParam String description, @RequestParam String homepage);

}

メソッドパラメーター

アノテーション付きの HTTP 交換メソッドは、次のメソッドパラメーターを使用して柔軟なメソッドシグネチャーをサポートします。

メソッド引数 説明

URI

アノテーションの url 属性をオーバーライドして、リクエストの URL を動的に設定します。

HttpMethod

アノテーションの method 属性をオーバーライドして、リクエストの HTTP メソッドを動的に設定します

@RequestHeader

リクエストヘッダーまたは複数のヘッダーを追加します。引数は、複数のヘッダーを持つ Map<String, ?> または MultiValueMap<String, ?>、値の Collection<?>、または個々の値です。文字列以外の値の型変換がサポートされています。

@PathVariable

リクエスト URL にプレースホルダーを展開するための変数を追加します。引数は、複数の変数を持つ Map<String, ?>、または個別の値の場合があります。文字列以外の値では型変換がサポートされています。

@RequestBody

リクエストの本文を、直列化するオブジェクトとして、または Reactive Streams Publisher (MonoFlux など)、構成済みの ReactiveAdapterRegistry でサポートされるその他の非同期型として提供します。

@RequestParam

リクエストパラメーターまたは複数のパラメーターを追加します。引数は、複数のパラメーターを持つ Map<String, ?> または MultiValueMap<String, ?>、値の Collection<?>、または個々の値の場合があります。文字列以外の値の型変換がサポートされています。

"content-type" が "application/x-www-form-urlencoded" に設定されている場合、リクエストパラメーターはリクエスト本文にエンコードされます。それ以外の場合は、URL クエリパラメーターとして追加されます。

@RequestPart

リクエストパートを追加します。リクエストパートは、String (フォームフィールド)、Resource (ファイルパート)、Object (JSON などでエンコードされるエンティティ)、HttpEntity (パートのコンテンツとヘッダー)、Spring Part、または上記のいずれかの Reactive Streams Publisher です。

@CookieValue

1 つまたは複数の Cookie を追加します。引数は、複数の Cookie を持つ Map<String, ?> または MultiValueMap<String, ?>、値の Collection<?>、または個々の値です。文字列以外の値の型変換がサポートされています。

戻り値

アノテーション付きの HTTP 交換メソッドは、次の戻り値をサポートします。

メソッドの戻り値 説明

void, Mono<Void>

指定されたリクエストを実行し、レスポンスコンテンツがある場合はそれを解放します。

HttpHeaders, Mono<HttpHeaders>

指定されたリクエストを実行し、レスポンスコンテンツがある場合はそれを解放して、レスポンスヘッダーを返します。

<T>, Mono<T>

指定されたリクエストを実行し、レスポンスの内容を宣言された戻り値の型にデコードします。

<T>, Flux<T>

指定されたリクエストを実行し、レスポンスコンテンツを宣言された要素型のストリームにデコードします。

ResponseEntity<Void>, Mono<ResponseEntity<Void>>

指定されたリクエストを実行し、レスポンスコンテンツがある場合はそれを解放して、ステータスとヘッダーを含む ResponseEntity を返します。

ResponseEntity<T>, Mono<ResponseEntity<T>>

指定されたリクエストを実行し、レスポンスコンテンツを宣言された戻り値の型にデコードし、ステータス、ヘッダー、デコードされた本文を含む ResponseEntity を返します。

Mono<ResponseEntity<Flux<T>>

指定されたリクエストを実行し、レスポンスコンテンツを宣言された要素型のストリームにデコードし、ステータス、ヘッダー、デコードされたレスポンス本文ストリームを含む ResponseEntity を返します。

ReactiveAdapterRegistry に登録されている他の非同期型またはリアクティブ型を使用することもできます。

例外処理

デフォルトでは、WebClient は 4xx および 5xx HTTP ステータスコードに対して WebClientResponseException を発生させます。これをカスタマイズするには、クライアントを介して実行されるすべてのレスポンスに適用されるレスポンスステータスハンドラーを登録します。

WebClient webClient = WebClient.builder()
		.defaultStatusHandler(HttpStatusCode::isError, resp -> ...)
		.build();

WebClientAdapter clientAdapter = WebClientAdapter.forClient(webClient);
HttpServiceProxyFactory factory = HttpServiceProxyFactory
		.builder(clientAdapter).build();

エラーステータスコードの抑制などの詳細とオプションについては、WebClient.Builder の defaultStatusHandler の Javadoc を参照してください。