Spring Boot + GitHub Search APIで簡単な検索フォームを作ってみました。


#記事を読む対象者
・初めて外部APIを使う方
・spring−boot初学者

を想定して書いています。

#目的
各企業がマイクロサービスを作って、外部APIとして提供していることは多いかと思います。
その中で、外部APIを自分のサービスに取り込む時に、クライアントライブラリの使い方、Json形式のデータからJavaオブジェクトへのマッピング等の基本となる使い方を学んでおくことで、今後の業務に役立てたいと思っています。

#成果物

![GithubAPITest.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537759/e764d0fb-aea3-5116-427e-c7163399c91c.gif)


GitHub Search APIを叩いて、リポジトリを言語別に検索し、リポジトリ名とユーザー名、リポジトリの概要を取得、表示する内容になっています。


#環境
FW：spring-boot 2.2.5
テンプレートエンジン：thymeleaf 3.0.4
HTTPクライアントライブラリ：okhttp3 4.4.1
JsonからJavaオブジェクトの相互変換ライブラリ：gson 2.8.6

プロジェクト管理には、Mavenを使用しているので、pom.xmlに依存関係を記述をしています。

```xml:pom.xml
<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.4.1</version>
</dependency>
<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.6</version>
</dependency>
```

#GitHub Search APIについて

[GitHub Search API公式](https://developer.github.com/v3/search/#search-repositories)

リポジトリ、ユーザー、issueやPRの検索が出来ます。
使い方が非常にシンプルで、事前に会員登録等は必要有りません（ただ、リクエストの回数制限有り）。

```
https://api.github.com/search/repositories?q=検索ワード
```

`https://api.github.com/search/repositories?q=java`
試しに上のURLをブラウザに入力してみると、「java」という検索ワードで検索された結果がブラウザに表示されることがわかると思います。
`?q=検索ワード+language:ruby`のようにカスタマイズすることでプログラム言語を検索したり、ソートさせたりすることも出来ます（詳細は上記URL参照）。

この内容を後は、Json→Javaに変換して、Thymeleafで表示します。

#ソースコード解説

##Gson

[【Java】JSONをJavaに、JavaをJSONにする　～GSONとJacksonの使用方法～](https://qiita.com/riversun/items/cdd990e96c2bbf9cb043)

上の内容通りにまずはJsonのパラメーターをJavaに格納するためのPOJOを作成します。
具体的には、APIを適当に叩き、ブラウザに表示されたパラメーターをコピペして、`jsonschema2pojo`でPOJOを作成しました。めちゃめちゃ便利。。。

`jsonschema2pojo`を使用したら、Example,Item,Ownerの３つのクラスが生成されると思います。僕は、`Example`のみ`ResultApi`と名前を変更しました。


`@SerializedName`
>@SerializedNameアノテーション（com.google.gson.annotations.SerializedName）を対象メンバに付与することでJSON出力時の項目名を好きな値に変更することができます。

`@Expose`
>標準のSerializableではtransientを付けたフィールドはシリアライズされない（保存されない）。
Gsonでは、Exposeアノテーションを付けたフィールドだけシリアライズ対象にするという事が出来る。

引用元：[GSON1](https://blog.y-yuki.net/entry/2016/11/25/000000)、[GSON2](http://www.ne.jp/asahi/hishidama/home/tech/java/google/gson.html)


##okhttp3

[JavaでJSONをPOSTする方法　～OkHttp3を使った方法とHttpUrlConnectionを使った方法～](https://qiita.com/riversun/items/4e0a1b6bea42ae1405c4)を参考にしました。

普段、我々がWebサーバーにアクセスするときは、ブラウザ経由でHTTP通信をしてアクセスをしていますが、リクエスト内容は検索ワードのみで、特別何も意識せずに、ブラウザに表示してくれています。それをプログラムで行う際に、リクエストを発行して、クライアント情報を作成して、HTTP通信を実行して、レスポンス結果を格納して...等を簡単に行ってくれるライブラリです。

##コントローラー


```java:DemoGetApiController.java
@Controller
public class DemoGetApiController {

	@ModelAttribute
	ResultApi init() {
		return new ResultApi();
	}

	@GetMapping("/apitest")
	String readme(Model model) throws IOException {
		return "rest/apiTest";
	}

	@PostMapping("/apitest")
	String search(
			@RequestParam(name = "target", required = false) String target,
			@RequestParam(name = "language", required = false) String language,
			Model model) throws IOException {

		//URLの作成。ポスト通信時に検索ワードとラジオボタンを取得して、URLに格納しています。
		String url = "https://api.github.com/search/repositories?q=" + target + "+" + "language:" + language;

		//HTTP通信に必要な情報を用意しています。最終的に結果が、ResponseBodyに格納されます。
		OkHttpClient client = new OkHttpClient();
		Request request = new Request.Builder().url(url).build();
		Call call = client.newCall(request);
		Response response = call.execute();
		ResponseBody body = response.body();

		//json形式の情報をjsonschema2pojoで作成したPOJOに格納しています。
		String json = body.string();
		Gson gson = new Gson();
		ResultApi resultApi = gson.fromJson(json, ResultApi.class);

		model.addAttribute("resultApi", resultApi);
		return "rest/apiTestResult";
	}
}
```

`@RequestParam(name = "target", required = false) String target`は検索ワードが格納されます。
`@RequestParam(name = "language", required = false) String language`はラジオボタンのプログラミング言語が格納されます。

GsonやHttp3の詳細な使い方は上記URLを参考にしていただければと思います。
POJOのResultApi・Item・Ownerは省略しています。

##ビュー
```html:apiTest
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
<link href="/css/style.css" th:href="@{/css/style.css}" rel="stylesheet" type="text/css"></link>
<title>テスト</title>
</head>
<body>
	<form th:action="@{'/apitest'}" method="post">
		<input type="text" name="target">
		<button>検索</button>
		<p>
			<label><input type="radio" name="language" value="java" checked>java</label>
			<label><input type="radio" name="language" value="ruby">ruby</label>
			<label><input type="radio" name="language" value="c#">c#</label>
			<label><input type="radio" name="language" value="python">python</label>
			<label><input type="radio" name="language" value="javascript">javascript</label>
			<label><input type="radio" name="language" value="c"> c</label>
		</p>
	</form>
</body>
</html>
```

```html:apiTestResult
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
<link href="/css/style.css" th:href="@{/css/style.css}" rel="stylesheet"
	type="text/css"></link>
<title>テスト</title>
</head>
<body>
	<a th:href="@{'/apitest'}">戻る</a>
	<div class="gitContents">
		<div class="card card-skin" th:each="item, stat : ${resultApi.items}">
			<div class="card__imgframe">
				<img th:src="${item.owner.avatarUrl}">
			</div>
			<div class="card__textbox">
				<div class="card__titletext">
					<a th:href="${item.htmlUrl}"><span th:text="${item.name}"></span></a>
				</div>
				<div class="card__overviewtext">
					<ul>
						<li>USER : <span th:text="${item.owner.login}"></span></li>
						<li>DESCRIPTION : <span th:text="${item.description}"></span></li>
					</ul>
				</div>
			</div>
		</div>
	</div>
</body>
</html>
```

今回は、USER名とリポジトリの概要を抽出して表示しています。その他にも、スターの数、フォークされた数等も取得することが出来ます。CSSは省略。

#感想
基本的な外部APIの使い方は学べたと思います。次は、逆にAPIを作って、Json形式に出力するといったことにもチャレンジしたいと思います！！