RestTemplate で REST API の利用

このガイドでは、RESTful Web サービスを使用するアプリケーションを作成するプロセスを順を追って説明します。

構築するもの

Spring の RestTemplate を使用して、http://localhost:8080/api/random でランダムな Spring Boot の引用を取得するアプリケーションを作成します。

必要なもの

本ガイドの完成までの流れ

ほとんどの Spring 入門ガイドと同様に、最初から始めて各ステップを完了するか、すでに慣れている場合は基本的なセットアップステップをバイパスできます。いずれにしても、最終的に動作するコードになります。

最初から始めるには、Spring Initializr から開始に進みます。

基本をスキップするには、次の手順を実行します。

完了したときは、gs-consuming-rest/complete のコードに対して結果を確認できます。

Spring Initializr から開始

IDE を使用する場合はプロジェクト作成ウィザードを使用します。IDE を使用せずにコマンドラインなどで開発する場合は、この事前に初期化されたプロジェクトからプロジェクトを ZIP ファイルとしてダウンロードできます。このプロジェクトは、このチュートリアルの例に合うように構成されています。

プロジェクトを手動で初期化するには:

  1. IDE のメニューまたはブラウザーから Spring Initializr を開きます。アプリケーションに必要なすべての依存関係を取り込み、ほとんどのセットアップを行います。

  2. Gradle または Maven のいずれかと、使用する言語を選択してください。

  3. 依存関係をクリックして、HTTP クライアントを選択します。

  4. 生成をクリックします。

  5. 結果の ZIP ファイルをダウンロードします。これは、選択して構成された Web アプリケーションのアーカイブです。

Eclipse や IntelliJ のような IDE は新規プロジェクト作成ウィザードから Spring Initializr の機能が使用できるため、手動での ZIP ファイルのダウンロードやインポートは不要です。
プロジェクトを GitHub からフォークして、IDE または他のエディターで開くこともできます。

REST リソースの取得

プロジェクトのセットアップが完了すると、RESTful サービスを使用する単純なアプリケーションを作成できます。

その前に、REST リソースのソースが必要です。そのようなサービスの例を https://github.com/spring-guides/quoters (英語) で提供しました。そのアプリケーションを別のターミナルで実行し、http://localhost:8080/api/random で結果にアクセスできます。そのアドレスは Spring Boot に関する見積もり用をランダムに取得し、それを JSON ドキュメントとして返します。その他の有効なアドレスには、http://localhost:8080/api/ (すべての見積もり用) および http://localhost:8080/api/1 (最初の見積もり用)、http://localhost:8080/api/2 (2 番目の見積もり用) などがあります (現時点では最大 10 個)。

Web ブラウザーまたは curl を介してその URL をリクエストすると、次のような JSON ドキュメントを受け取ります。

{
   type: "success",
   value: {
      id: 10,
      quote: "Really loving Spring Boot, makes stand alone Spring apps easy."
   }
}

これは十分に簡単ですが、ブラウザーや curl を介して取得する場合は、それほど便利ではありません。

REST Web サービスを利用するより便利なメソッドは、プログラムを使用することです。そのタスクを支援するために、Spring は RestClient (Javadoc) と呼ばれる便利なテンプレートクラスを提供します。RestClient は、ほとんどの RESTful サービスとの対話を 1 行の呪文にします。また、そのデータをカスタムドメイン型にバインドすることもできます。

まず、必要なデータを格納するためのドメインクラス(Java レコードクラス、または Kotlin データクラス)を作成する必要があります。以下のリストは、ドメインクラスとして使用できる Quote クラスを示しています。

Java
package com.example.consumingrest;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties(ignoreUnknown = true)
public record Quote(String type, Value value) { }
Kotlin
package com.example.consumingrest

import com.fasterxml.jackson.annotation.JsonIgnoreProperties

@JsonIgnoreProperties(ignoreUnknown = true)
data class Quote(
  val type: String,
  val value: Value
)

ドメインクラスには、Jackson JSON 処理ライブラリの @JsonIgnoreProperties アノテーションが付けられ、この型にバインドされていないプロパティは無視されることを示します。

データをカスタム型に直接バインドするには、API から返された JSON ドキュメントのキーとまったく同じになるように変数名を指定する必要があります。JSON ドキュメントの変数名とキーが一致しない場合、@JsonProperty アノテーションを使用して JSON ドキュメントの正確なキーを指定できます。(この例では、各変数名を JSON キーに一致させるため、ここでそのアノテーションは必要ありません。)

内部引用符自体を埋め込むには、追加のドメインクラスも必要です。次のように、Value クラスがそのニーズを満たします。

Java
package com.example.consumingrest;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties(ignoreUnknown = true)
public record Value(Long id, String quote) { }
Kotlin
package com.example.consumingrest

import com.fasterxml.jackson.annotation.JsonIgnoreProperties

@JsonIgnoreProperties(ignoreUnknown = true)
data class Value(
  val id: Long,
  val quote: String
)

これは同じアノテーションを使用しますが、他のデータフィールドにマップします。

アプリケーションの終了

Initializr は、次のように、main() メソッドを持つクラスを作成します。

Java
package com.example.consumingrest;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ConsumingRestApplication {

  public static void main(String[] args) {
    SpringApplication.run(ConsumingRestApplication.class, args);
  }

}
Kotlin
package com.example.consumingrest

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication

@SpringBootApplication
class ConsumingRestApplication

fun main(args: Array<String>) {
  runApplication<ConsumingRestApplication>(*args)
}

次に、他のいくつかを ConsumingRestApplication クラスに追加して、RESTful ソースからの引用を表示する必要があります。以下を追加する必要があります。

  • ログ(この例ではコンソール)に出力を送信するロガー。

  • 自動構成された RestClient.Builder を使用して RestClient インスタンスを構築し、起動時にそれを使用して引用を取得する CommandLineRunner。

次のリストは、完成した ConsumingRestApplication クラスを示しています。

Java
package com.example.consumingrest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Profile;
import org.springframework.web.client.RestClient;

@SpringBootApplication
public class ConsumingRestApplication {

  private static final Logger log = LoggerFactory.getLogger(ConsumingRestApplication.class);

  public static void main(String[] args) {
    SpringApplication.run(ConsumingRestApplication.class, args);
  }

  @Bean
  @Profile("!test")
  public ApplicationRunner run(RestClient.Builder builder) {
    RestClient restClient = builder.baseUrl("http://localhost:8080").build();
    return args -> {
      Quote quote = restClient
          .get().uri("/api/random")
          .retrieve()
          .body(Quote.class);
      log.info(quote.toString());
    };
  }
}
Kotlin
package com.example.consumingrest

import org.slf4j.LoggerFactory
import org.springframework.boot.ApplicationRunner
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Profile
import org.springframework.web.client.RestClient
import org.springframework.web.client.toEntity

private val log = LoggerFactory.getLogger(ConsumingRestApplication::class.java)

@SpringBootApplication
class ConsumingRestApplication {

  @Bean
  @Profile("!test")
  fun run(builder: RestClient.Builder) = ApplicationRunner {
    val quote = builder.build().get().uri("http://localhost:8080/api/random")
      .retrieve().toEntity<Quote>()
    log.info(quote.toString())
  }
}

fun main(args: Array<String>) {
  runApplication<ConsumingRestApplication>(*args)
}

アプリケーションの実行

コマンドラインから Gradle または Maven を使用してアプリケーションを実行できます。必要なすべての依存関係、クラス、リソースを含む単一の実行可能 JAR ファイルを構築して実行することもできます。実行可能な jar を構築すると、開発ライフサイクル全体、さまざまな環境などで、アプリケーションとしてサービスを簡単に提供、バージョン管理、デプロイできます。

Gradle を使用する場合、./gradlew bootRun を使用してアプリケーションを実行できます。または、次のように、./gradlew build を使用して JAR ファイルをビルドしてから、JAR ファイルを実行できます。

java -jar build/libs/gs-consuming-rest-0.0.1-SNAPSHOT.jar

Maven を使用する場合、./mvnw spring-boot:run を使用してアプリケーションを実行できます。または、次のように、./mvnw clean package で JAR ファイルをビルドしてから、JAR ファイルを実行できます。

java -jar target/gs-consuming-rest-0.0.1-SNAPSHOT.jar

次のような出力が表示されますが、ランダムな引用が表示されます。

2019-08-22 14:06:46.506  INFO 42940 --- [           main] c.e.c.ConsumingRestApplication           : Quote{type='success', value=Value{id=1, quote='Working with Spring Boot is like pair-programming with the Spring developers.'}}
Could not extract response: no suitable HttpMessageConverter found for response type [class com.example.consumingrest.Quote] というエラーが表示された場合は、バックエンドサービスに接続できない環境にいる可能性があります (接続できれば JSON が送信されます)。もしかしたら、企業のプロキシの後ろにいるかもしれません。http.proxyHost と http.proxyPort のシステムプロパティを環境に適した値に設定してみてください。

要約

おめでとう! Spring Boot を使用して、簡単な REST クライアントを開発しました。

コードを入手する