1. 概要

このチュートリアルでは、Spring RESTクライアント( RestTemplate )を使用でき、適切に使用できるさまざまな操作について説明します。

すべての例のAPI側では、ここからRESTfulサービスを実行します。

2. 非推奨の通知

Spring Framework 5の時点で、SpringはWebFluxスタックとともに、WebClientと呼ばれる新しいHTTPクライアントを導入しました。

WebClient は、RestTemplateの最新の代替HTTPクライアントです。 従来の同期APIを提供するだけでなく、効率的なノンブロッキングおよび非同期アプローチもサポートします。

そうは言っても、新しいアプリケーションを開発している場合や古いアプリケーションを移行している場合は、 WebClientを使用することをお勧めします。 今後、RestTemplateは将来のバージョンで非推奨になります。

3. GETを使用してリソースを取得する

3.1. プレーンJSONを取得する

簡単に始めて、GETリクエストについて話しましょう。はgetForEntity()APIを使用した簡単な例です。

RestTemplate restTemplate = new RestTemplate();
String fooResourceUrl
  = "http://localhost:8080/spring-rest/foos";
ResponseEntity<String> response
  = restTemplate.getForEntity(fooResourceUrl + "/1", String.class);
Assertions.assertEquals(response.getStatusCode(), HttpStatus.OK);

HTTP応答に完全にアクセスできることに注意してください。これにより、ステータスコードをチェックして、操作が成功したことを確認したり、応答の実際の本文を操作したりできます。

ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(response.getBody());
JsonNode name = root.path("name");
Assertions.assertNotNull(name.asText());

ここでは、応答本文を標準の文字列として使用し、Jackson(およびJacksonが提供するJSONノード構造)を使用して詳細を確認しています。

3.2. JSONの代わりにPOJOを取得する

応答をリソースDTOに直接マッピングすることもできます。

public class Foo implements Serializable {
    private long id;

    private String name;
    // standard getters and setters
}

これで、テンプレートで getForObjectAPIを使用するだけで済みます。

Foo foo = restTemplate
  .getForObject(fooResourceUrl + "/1", Foo.class);
Assertions.assertNotNull(foo.getName());
Assertions.assertEquals(foo.getId(), 1L);

4. HEADを使用してヘッダーを取得する

次に、より一般的な方法に進む前に、HEADの使用について簡単に見てみましょう。

ここでは、 headForHeaders()APIを使用します。

HttpHeaders httpHeaders = restTemplate.headForHeaders(fooResourceUrl);
Assertions.assertTrue(httpHeaders.getContentType().includes(MediaType.APPLICATION_JSON));

5. POSTを使用してリソースを作成する

APIで新しいリソースを作成するために、 postForLocation() postForObject()、または postForEntity()APIをうまく利用できます。

1つ目は新しく作成されたリソースのURIを返し、2つ目はリソース自体を返します。

5.1. postForObject() API

RestTemplate restTemplate = new RestTemplate();

HttpEntity<Foo> request = new HttpEntity<>(new Foo("bar"));
Foo foo = restTemplate.postForObject(fooResourceUrl, request, Foo.class);
Assertions.assertNotNull(foo);
Assertions.assertEquals(foo.getName(), "bar");

5.2. postForLocation() API

同様に、完全なリソースを返す代わりに、新しく作成されたリソースのLocationを返す操作を見てみましょう。

HttpEntity<Foo> request = new HttpEntity<>(new Foo("bar"));
URI location = restTemplate
  .postForLocation(fooResourceUrl, request);
Assertions.assertNotNull(location);

5.3. exchange() API

より一般的なexchangeAPIを使用してPOSTを実行する方法を見てみましょう。

RestTemplate restTemplate = new RestTemplate();
HttpEntity<Foo> request = new HttpEntity<>(new Foo("bar"));
ResponseEntity<Foo> response = restTemplate
  .exchange(fooResourceUrl, HttpMethod.POST, request, Foo.class);
 
Assertions.assertEquals(response.getStatusCode(), HttpStatus.CREATED);
 
Foo foo = response.getBody();
 
Assertions.assertNotNull(foo);
Assertions.assertEquals(foo.getName(), "bar");

5.4. フォームデータの送信

次に、POSTメソッドを使用してフォームを送信する方法を見てみましょう。

まず、Content-Typeヘッダーをapplication/x-www-form-urlencoded。に設定する必要があります。

これにより、名前と値のペアがで区切られた大きなクエリ文字列をサーバーに送信できるようになります。

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

フォーム変数をLinkedMultiValueMapにラップできます。

MultiValueMap<String, String> map= new LinkedMultiValueMap<>();
map.add("id", "1");

次に、HttpEntityインスタンスを使用してリクエストを作成します。

HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);

最後に、エンドポイントで restTemplate.postForEntity()を呼び出すことにより、RESTサービスに接続できます: / foos / form

ResponseEntity<String> response = restTemplate.postForEntity(
  fooResourceUrl+"/form", request , String.class);
Assertions.assertEquals(response.getStatusCode(), HttpStatus.CREATED);

6. OPTIONSを使用して許可された操作を取得する

次に、OPTIONSリクエストの使用方法と、この種のリクエストを使用した特定のURIで許可されている操作について簡単に説明します。 APIはoptionsForAllowです。

Set<HttpMethod> optionsForAllow = restTemplate.optionsForAllow(fooResourceUrl);
HttpMethod[] supportedMethods
  = {HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE};
Assertions.assertTrue(optionsForAllow.containsAll(Arrays.asList(supportedMethods)));

7. PUTを使用してリソースを更新する

次に、 template.put APIは非常に単純なので、PUT、より具体的にはこの操作の exchange()APIについて見ていきます。

7.1. シンプルなPUT付き 両替()

APIに対する単純なPUT操作から始めます。この操作は、本文をクライアントに返さないことに注意してください。

Foo updatedInstance = new Foo("newName");
updatedInstance.setId(createResponse.getBody().getId());
String resourceUrl = 
  fooResourceUrl + '/' + createResponse.getBody().getId();
HttpEntity<Foo> requestUpdate = new HttpEntity<>(updatedInstance, headers);
template.exchange(resourceUrl, HttpMethod.PUT, requestUpdate, Void.class);

7.2. exchange()とリクエストコールバックを使用したPUT

次に、リクエストコールバックを使用してPUTを発行します。

コールバックを準備していることを確認しましょう。ここで、必要なすべてのヘッダーとリクエスト本文を設定できます。

RequestCallback requestCallback(final Foo updatedInstance) {
    return clientHttpRequest -> {
        ObjectMapper mapper = new ObjectMapper();
        mapper.writeValue(clientHttpRequest.getBody(), updatedInstance);
        clientHttpRequest.getHeaders().add(
          HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
        clientHttpRequest.getHeaders().add(
          HttpHeaders.AUTHORIZATION, "Basic " + getBase64EncodedLogPass());
    };
}

次に、POSTリクエストを使用してリソースを作成します。

ResponseEntity<Foo> response = restTemplate
  .exchange(fooResourceUrl, HttpMethod.POST, request, Foo.class);
Assertions.assertEquals(response.getStatusCode(), HttpStatus.CREATED);

次に、リソースを更新します。

Foo updatedInstance = new Foo("newName");
updatedInstance.setId(response.getBody().getId());
String resourceUrl =fooResourceUrl + '/' + response.getBody().getId();
restTemplate.execute(
  resourceUrl, 
  HttpMethod.PUT, 
  requestCallback(updatedInstance), 
  clientHttpResponse -> null);

8. DELETEを使用してリソースを削除します

既存のリソースを削除するには、 delete()APIをすばやく使用します。

String entityUrl = fooResourceUrl + "/" + existingResource.getId();
restTemplate.delete(entityUrl);

9. タイムアウトの構成

ClientHttpRequestFactory を使用するだけで、タイムアウトするようにRestTemplateを構成できます。

RestTemplate restTemplate = new RestTemplate(getClientHttpRequestFactory());

private ClientHttpRequestFactory getClientHttpRequestFactory() {
    int timeout = 5000;
    HttpComponentsClientHttpRequestFactory clientHttpRequestFactory
      = new HttpComponentsClientHttpRequestFactory();
    clientHttpRequestFactory.setConnectTimeout(timeout);
    return clientHttpRequestFactory;
}

また、 HttpClient を使用して、さらに構成オプションを設定できます。

private ClientHttpRequestFactory getClientHttpRequestFactory() {
    int timeout = 5000;
    RequestConfig config = RequestConfig.custom()
      .setConnectTimeout(timeout)
      .setConnectionRequestTimeout(timeout)
      .setSocketTimeout(timeout)
      .build();
    CloseableHttpClient client = HttpClientBuilder
      .create()
      .setDefaultRequestConfig(config)
      .build();
    return new HttpComponentsClientHttpRequestFactory(client);
}

10. 結論

この記事では、 RestTemplate を使用してメインのHTTP動詞を調べ、これらすべてを使用してリクエストを調整しました。

テンプレートを使用して認証を行う方法を詳しく知りたい場合は、RestTemplateを使用した基本認証に関する記事を確認してください。

これらすべての例とコードスニペットの実装は、GitHubにあります。