一部省略箇所
- IDEAは前回設定済みなので割愛
- 今回のプロジェクトのダウンロード方法も前回と同じ方法なので割愛
Consuming a RESTful Web Service
日本語Verと英語Ver、多分
✅RestTemplateについて
RESTful Web サービスを使用するアプリケーションを作成するプロセスを順を追って説明
Spring の RestTemplate を使用して、http://localhost:8080/api/random
でランダムな Spring Boot の引用を取得するアプリケーションを作成する
このチュートリアルのゴール
「外部または内部のREST APIを呼び出して、JSON形式のデータを取得し、Javaオブジェクトに変換して使う」こと
Fetching a REST Resource(REST リソースの取得)
0:Githubからクローン
-
これからREST API から「名言(Quote)」を取得して表示するモノを作成するにあたり、事前に 「引用(Quote)を提供してくれる API(サーバー)」 を準備する必要がある
-
1:GitHubにあるサンプルAPIプロジェクト(quoters)をダウンロード or クローンする
👉 https://github.com/spring-guides/quoters- ページ右上にある「Code」→「Download ZIP」でダウンロード
- 解凍して IDEAエディタで「quoters」フォルダに移動
-
2:そのプロジェクトを自分のPCで起動しておく(Spring Bootアプリとして)
1:まず前提:何をしたいのか?
Spring Bootを使って、外部のWebサービス(REST API)からデータを取り出して使うアプリを作ろう!という内容。
2: REST APIって何?
「Webの住所(URL)にアクセスすると、データ(JSON形式)が返ってくる」サービスのこと。
例:http://localhost:8080/api/random
にアクセスすると、名言(Quote)がランダムで返ってくる。
{
"type": "success",
"value": {
"id": 10,
"quote": "Really loving Spring Boot, makes stand alone Spring apps easy."
}
}
第1階層
type:文字列(例: "success")
value:オブジェクト(入れ子)
第2階層
id:数値(例: 10)
quote:文字列(例: "Really loving...")
3:どうやってデータをもらうのか?
ブラウザや curl
コマンドでアクセスして、JSONデータを見ることはできる。
でも それだけでは便利とはいえない。
→ Javaプログラムの中で自動で取得して使えるようにするのが目的。
4:RestTemplate とは何か?
Spring
が用意している、Webからデータを取ってくる道具。
1行でAPIにアクセスし、JSONをJavaのオブジェクトにしてくれる便利なクラス!
5:JSONのデータを受け取るには「型(クラス)」が必要
データをうまく受け取るために、次の2つのクラス(record)を作る
👆ここまで前提。以下ファイル作成etc
必要なデータを格納するドメインクラスを作成
package com.example.consumingrest;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@JsonIgnoreProperties(ignoreUnknown = true)
// typeはString型。valueはValue型
public record Quote(String type, Value value) { }
Quoteクラス
type(成功したかどうか)と value(実際の名言)を持っている
value はさらに別のオブジェクト(Value)として扱う
- 必要なデータ:APIから返ってくるJSONデータ。つまりレスポンスボディのこと。
今回のチュートリアルでは最初に例として「type」「id」「quote」が明示されている
返ってきたデータはそのままプログラムの中では利用できない - 受け取ったデータを操作するには「クラス」にしないと使えない(Java は静的型付け言語なので、データの「構造」がはっきりしていないと使えない。)
- なので「JSON 構造に対応するクラス」が必要である。この「クラス」のことを「ドメインクラス」という
- 第一階層部分について。
外側全体(type と value)を表すQuoteというクラスは「"quote"(JSONのキー名)」とは別物。
今回たまたま一緒になっただけ。
- この value は、Value クラスのインスタンスを格納する変数
内部引用符自体を埋め込むための追加クラスも必要.ここは第2階層部分に該当。つまりvalueの中身。
package com.example.consumingrest;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@JsonIgnoreProperties(ignoreUnknown = true)
// idはLong型。quoteはString型(文字列)
public record Value(Long id, String quote) { }
Valueクラス
id: 名言の番号
quote: 実際の名言の文章
👇少し混乱した。よくある例?型とクラス
Value value = new Value(1L, "Spring Boot is awesome!");
Value(左側)→ 型(データの種類)
Value(右側)→ クラス名(new でオブジェクト生成)
value → オブジェクト(Value 型の変数
6:@JsonIgnoreProperties
の意味
- JSONから返ってくるボディに余分なキーが返ってきてエラーになるのを防ぐために
@JsonIgnoreProperties
を使用する - 今回
Quote
クラスの中にtype, valueキー
がある。またValue
クラスの中にid, quoteキー
がある。
↓もう少し簡潔に言うと
- JSONの中に、Javaのクラスにない項目があっても無視してくれる
- たとえば、APIが将来新しい項目を追加してもエラーにならないようにする
7:JSONのキーとJavaの変数名は合わせる
- JSONのキーとJavaの変数名は同じ名前にする必要がある。
- もし名前が違う場合は、
@JsonProperty("jsonのキー名")
を使って教えてあげる。(今回は名前が一致しているので不要)
ここまでの内容まとめ
ステップ | 内容 |
---|---|
APIとは? | URLにアクセスするとJSONが返ってくるWebサービス |
JSONの例 | {"type":"success", "value":{"id":10, "quote":"..."}} |
RestTemplate | APIにアクセスして、データをオブジェクトにしてくれる |
Quote クラス | JSONの外側を表すクラス(type とvalue ) |
Value クラス | 名言そのものを表すクラス(id とquote ) |
アノテーション | JSONとJavaの連携を助ける(例:@JsonIgnoreProperties ) |
Finishing the Application(アプリケーションの終了)
このステップでやること:REST API から名言(Quote)を取り出して、実際にJavaプログラムで表示したい!
👇まず、現段階(DLしたファイルのコード)では、最も基本的なSpring Bootアプリの構成状態。(ただ「アプリを起動するだけ」で、何もしていない)
→つまり、ここには 「REST APIを呼び出す機能」や「JSONを受け取る機能」 がない状態
// namespaceのようなもの
package com.example.consuming_rest;
// Spring Bootアプリケーション起動用クラス
import org.springframework.boot.SpringApplication;
// 自動設定アノテーション(注釈)
import org.springframework.boot.autoconfigure.SpringBootApplication;
// Spring Bootの基本設定(自動構成やコンポーネントスキャンなど)
@SpringBootApplication
public class ConsumingRestApplication {
// Javaアプリの入り口(最初に実行されるメソッド)
public static void main(String[] args) {
// Spring Bootのアプリを起動する(設定を読み込んで準備)
SpringApplication.run(ConsumingRestApplication.class, args);
}
}
上記、初期状態が確認出来たらチュートリアル記載のコードに変更していきます
package com.example.consumingrest;
// 1:ログ出力を行うためのライブラリをインポート(結果や状態をコンソールに出す)
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// 2:起動時に特定の処理を実行するためのインターフェース
import org.springframework.boot.CommandLineRunner;
// Spring Bootの起動や設定はそのまま(前と同じ)
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
// 3:RestTemplateを簡単に作成するためのビルダーをインポート
import org.springframework.boot.web.client.RestTemplateBuilder;
// 4:SpringのDI(依存性注入)用のアノテーションをインポート
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Profile;
// 5:REST API呼び出しに使うRestTemplateクラス
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class ConsumingRestApplication {
// 6:APIから受取った内容をログを出すための準備。ログを使って情報をコンソールに表示できるようにする
private static final Logger log = LoggerFactory.getLogger(ConsumingRestApplication.class);
public static void main(String[] args) {
SpringApplication.run(ConsumingRestApplication.class, args);
}
// 7:RestTemplate(HTTPで他のサーバーと通信するためのクラス)をBeanとして登録。これでSpring管理のオブジェクトになる
// @Beanで管理する事で、Springが自動で管理し、他のところで使い回せまるy。
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
// 8:アプリ起動時に1回だけ実行される処理を登録。APIを叩いて、データを取得して表示する
// @Profile("!test")はテスト実行時はこの処理をスキップするための設定
@Bean
@Profile("!test")
public CommandLineRunner run(RestTemplate restTemplate) throws Exception {
// 起動時に呼ばれるラムダ式(処理の中身)
return args -> {
// 9:RestTemplateを使ってREST APIからデータを取得(JSON→Quoteオブジェクトに変換)
Quote quote = restTemplate.getForObject("http://localhost:8080/api/random", Quote.class);
// 10:取得したデータをログ(コンソール)に表示する
log.info(quote.toString());
};
}
}
- REST APIを使ってJSONを取得・表示するアプリにするために変更。
- 具体的に分けると:
- ログを使うための準備(Loggerの追加)
- REST APIを呼ぶ準備(RestTemplateのBean登録)
- 起動時に処理を実行する仕組み(CommandLineRunner)
- 環境による起動制御(@ Profile)
- Spring管理のためのBean定義アノテーション(@ Bean)
★最後にポート番号の設定(server.port=8081)
REST APIサーバー(例: http: //localhost:8080/api/random)が動いていると、このアプリが同じ8080を使えないから(ポート重複エラーになる)設定する。
-
src/main/resources/
フォルダを開く -
application.properties
というファイルがあるか確認 - この中に
server.port=8081
を追記してターミナルor三角の再生マーク?で起動 - チュートリアルはじめの方で行ったGithubを完了させている状態で、「http: //localhost:8080/api/random」にいき、動作していればOK
おまけ
今回ValueとQuoteで記述した「@ JsonIgnoreProperties」に関するコードをコメント形式にしてもエラーは起こりませんでした。
参考