Java（Spring）で作るはじめてのAPI

# 記事の目的
JavaサーブレットやJSPを用いるWEBプログラミングを学んだ人へ、次のステップとしてJavaを使ったWeb APIの自作方法を解説します。  
これを知ることで、フロントエンドとバックエンドの開発を分離でき、より効率的に開発できるようになります。  
なお、この記事では、APIの設計方法のような高度な内容はありません。  
あくまで、簡単にAPIを作ってみよう！というノリの記事です。



# APIとは何か  
API（Application Programming Interface）は、ソフトウェアからOSの機能を利用するための仕様もしくはインターフェースの略称であり、アプリケーション開発を容易にするソフトウェア資源です。
Webアプリ開発に用いるAPIは「Web API」と呼ばれ、気象情報や統計情報などさまざまなものが用意されています。すでに用意されたAPIを利用するだけでなく、この記事で説明するように自分でAPIを作ることも可能です。
APIを使えば、よく使う機能を呼び出すだけで使え、一からプログラミングする必要がなくなるため開発が楽になります。

＜参考文献＞
https://mypage.otsuka-shokai.co.jp/contents/business-oyakudachi/words/api.html



# 使うもの　Spring Boot  
JavaでAPIを使うために、JavaのフレームワークであるSpring Bootを使います。
この他のフレームワークである、Spring Frameworkもありますが、こちらは便利で機能が豊富な一方で、「機能の使い分けが困難」というデメリットがあります。  
このようなデメリットを克服するために作られたのが、Spring Bootというフレームワークです。　Spring Frameworkで複数の機能を利用する場合に必要となる、Bean定義やXML設定を可能な限り自動設定する機能があります。  
なお、Spring BootはSpring Frameworkを構成する１つとして搭載されています。 

＜参考文献＞
 https://hnavi.co.jp/knowledge/blog/spring-boot/

# 使うもの　Fetch API
Spring Bootで作成したAPIへの接続方法として、今回はJavaScriptのFetch APIを使います。
本記事では、APIへのリクエストやレスポンスの処理について説明しますが、その他の仕様についてはこちら（https://developer.mozilla.org/ja/docs/Web/API/Fetch_API/Using_Fetch)
のリファレンスを参考にしてください。

# これからやること  
HTMLのフォームに自分の名前を入れると、APIが入力した名前に対する挨拶文を返し、画面に表示されるWebアプリを作ります。以下がその仕様です。

* 呼び出し（フロント）側  （HTML,JavaScript）
テキストエリアを使って、入力された名前テキストをAPIにリクエストとして渡す。  
APIから帰ってきた挨拶文を画面に表示する。
* あいさつAPI側　（Spring）
ブラウザからの名前を含むリクエストlocalhost:8080/helloを受け取り、挨拶文をJSON形式で返す

# 前提 
* HTML/CSS/JavaScriptの基礎を理解している
* Javaプログラミングの基礎を理解している  
* 開発環境であるEclipsをPCインストールしてある  

# 手順の概要
1. Springのプロジェクトを作成する  
2. リクエストhelloAPIで反応するプログラムを記述する
3. ＜呼び出し側＞HTMLを使ってUIを作成する
4. ＜呼び出し側＞JavaScriptを作ってテキストエリアの内容を取得し、APIを呼び出す
5. ＜呼び出し側＞APIから帰ってきた挨拶文をHTMLに埋め込む
6. APIを起動（Spring Bootアプリケーションを起動）してブラウザからアクセスする
  
# 詳細な手順  
### 1. Springプロジェクトを作成する
Eclipsを使ってSpringプロジェクトを作成します。  

メニュ > ファイル > 新規 > Springスターター・プロジェクト（Spring initializr）
を選ぶ。
![プロジェクト作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724591/e75a4bd3-f65f-fccc-0d19-286558f6ce9a.png)

「名前」、「タイプ」、「Javaバージョン」を設定して、次へをクリック。
![プロジェクト設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724591/233acef8-1697-7506-6d65-dd574986a5f5.png)

依存関係の設定については、今回は「Spring Web」のみ選択して、完了をクリック。
![プロジェクト設定2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724591/cdecab87-6ef1-a06b-6722-1f9b7897bfd5.png)

作成すると、画面左の「プロジェクト・エクスプローラー」にプロジェクトが追加される。  

### 2. リクエストhelloAPIで反応するプログラムを記述する

現在のディレクトリ構成（画面左側の「プロジェクト・エクスプローラー」に表示）は以下のようになっているはずです。  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724591/c9265645-d200-8337-8958-ffc6e0e99027.png)

hello_api[boot]の上を右クリックして、新規 > その他　を選ぶ  

「ウィザードを選択」画面が出てくるので、「クラス」を選択して、次へをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724591/35f43b9c-56a2-fb9c-bf92-4cda2b1414ce.png)

クラスを作成する画面が出るので、クラス名（今回はHelloController）を設定して、完了をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724591/1656129e-41af-1bcf-50fd-7bc2b0dd4451.png)

ファイルが作成されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724591/8c410875-8cd2-b082-6d92-7880b58e4aaa.png)

ファイルができたので、まずは、呼び出し側（ブラウザ側）からリクエストを受け取れるようにします。
以下の内容に変更します。  

```HelloController.java
package com.example.demo;

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@CrossOrigin
public class HelloController {
	@GetMapping("/helloAPI")
	public Message hello(@RequestParam(value = "name") String name) {
		//ここに処理を記述
	}
}

```
＠GetMapping("/helloAPI")は、リクエストを受ける時の名前を決めています。 
ここに指定した名前で、呼び出し元からこのプログラムを呼び出す（リクエストを送る）ことになります。  
この場合のリクエストは、localhost:8080//helloAPIになります。リクエストの詳細は3節で紹介します。  

＠GetMappingの次の行からは、このリクエストに対応したメソッドを記述します。
リクエスト元から受け取るnameという名前の値を、引数としてnameに格納します。
そして、返し値としてMessageを指定しています。これは、Messageクラスの形（フィールドのまとまり）で返すという意味です。


ということで、次はMessageクラスを作成します。

HelloController.javaを作成した同じ手順で、Messageクラスを作成します。  
作成したら、以下の内容に書き換えます。  

```Message.java
package com.example.demo;

public class Message {
	private String message;

	public Message(String message) {
		super();
		this.message = message;
	}

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}
}


```
javaを勉強している方はお分かりかと思いますが、messageというString型のフィールドに、コンストラクタやgetter,setterを使って格納・取り出すクラスです。  

今回は、挨拶文をmessageフィールドに格納し、このクラスのインスタンスを呼び出し元へ返すことになります。

Messageクラスが用意できたので、HelloControllerに、ブラウザから受け取った名前を使用して挨拶文を作成し、ブラウザへ返す処理を書いていきます。

次の内容へ変更します。　　
```HelloController.java
//前略...
@GetMapping("/helloAPI")
	public Message hello(@RequestParam(value = "name") String name) {
		String message = "こんにちは。" + name + "さん！";
		//Messageクラスのインスタンスを作成し、messageをセットする
		Message msg = new Message(message);
		return msg;
	}
//後略...
```
受け取った名前をもとに挨拶文を作成し、それをもとに先ほどのMessageクラスのインスタンス（msg）を作成しています。  
そして作ったインスタンス（msg）を呼び出し元へreturnしています。  

これで、API側の実装は完了しました。

### 3. ＜呼び出し側＞HTMLを使ってUIを作成する
今回は、以下の図のようなシンプルなWEBページを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724591/d472a458-0f71-2309-4afd-08b48e950a70.png)

お使いのPCの好きな場所に、hello.htmlというファイルを作成して下さい。  
作成したら、以下の内容を記述します。  
```hello.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title>はじめてのAPI</title>
  </head>

  <body>
    <h1>あいさつAPI</h1>
    <p>名前を教えて下さい</p>
    <input id="input" type="text" value="名前"/>
    <button type="button">送信！</button>
    <button type="button">クリア</button>
    <p id="text"></p>
  </body>
</html>
```
今回は簡単にUIを作成しました。もちろんCSSのファイルをリンクして装飾していただいても構いませんが、この記事では割愛します。

### 4. ＜呼び出し側＞JavaScriptを作ってテキストエリアの内容を取得し、APIを呼び出す

2章で作成したあいさつAPIを、htmlから使用（呼び出す）する処理を書きます。  
hello.htmlのbodyタグ内に、scriptタグを追加し、以下の内容を記述します。

```hello.html
<script>
      async function connectApi() {
        //テキストエリアの入力値を取得
        const inputValue = document.getElementById("input");
        const name = inputValue.value;
        try {
          const url = "http://localhost:8080/hello?name=" + name;
          //例外が発生した場合は、catchへ移動
          const response = await fetch(url, {
            method: "GET",
          });
        } catch (err_msg) {
          alert(err_msg);
        }
      }
    </script>
```

### 5. ＜呼び出し側＞APIから帰ってきた挨拶文をHTMLに埋め込む
4章で書いたコードは、APIを呼び出すだけだったので、帰ってきたものをHTML内に埋め込みます。以下のように書き換えます。  
```hello.html
<script>
      async function connectApi() {
        //テキストエリアの入力値を取得
        const inputValue = document.getElementById("input");
        const name = inputValue.value;
        try {
          const url = "http://localhost:8080/hello?name=" + name;
          //例外が発生した場合は、catchへ移動
          const response = await fetch(url, {
            method: "GET",
          });
          if (!response.ok) {
            switch (response.status) {
              default:
                //不明なエラーの場合は、ステータスを含めて表示する
                const err_code = response.status;
                const err_msg =
                  "情報を取得できませんでした。（E:" + err_code + ")";
                throw new Error(err_msg);
            }
          } else {
            const reserved = await response.json();
            //htmlのpタグ内に、受信したあいさつメッセージを表示
            const message = document.getElementById("text");
            message.textContent = reserved.message;
          }
        } catch (err_msg) {
          alert(err_msg);
        }
      }
    </script>
```

### 6.APIを起動（Spring Bootアプリケーションを起動）してブラウザからアクセスする
必要なコードは全て書けたので、APIを起動してブラウザからアクセスしてみましょう。  

Eclipsに戻って、画面左側の「プロジェクト・エクスプローラー」で、
hello_apiを右クリック > 実行 > Spring Boot アプリケーション　を選ぶ。  

Eclipsの「コンソール」の画面が、以下の図のようになれば起動成功です。  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724591/41274535-1e99-eb66-61ad-0eceab3ab7f0.png)

先ほど作ったhello.htmlをブラウザで開いて、名前を入れて「送信！」ボタンを押してみましょう。  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724591/35350986-bd1e-1bcb-ead6-08b10ae26d57.png)

↓「送信！」をクリックした後  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724591/07e28b6f-7409-d81d-7503-010773a26083.png)


はい！ あいさつAPIが完成しました。  
お疲れ様でした！