REST API基礎

# REST APIとは
- REST(REpresentational State Transfer)とは、Webサービスの設計ルール。
   - RESTful API、WebAPIと呼ばれることもある。
- Webサービスで提供している機能やデータを外からプログラムが読み取りやすい形で利用できるよう定めた規約又はその実装。
- サービスのURIにHTTPメソッドでアクセスすることでデータの送受信を行う。

# RESTの４原則
1. 統一インターフェース
1. アドレス可読性
1. 接続性
1. ステートレス性

### 統一インターフェース（Uniform Interface）
- あらかじめ定義・共有された方法でやり取りされる
   - HTTPリクエスト：GET/POST/PUT/DELETEなど
   - データの形式：JSON/XMLなど
   
        | 操作　| メソッド |
        |----|----|
        |Create|POST(*1)/PUT(*2)|
        |Read|GET |
        |Update|PUT|
        |Delete|DELETE|
        
        *1：リソース名が未定　*2：リソース名が決まっている
        参考：[PUT か POST か PATCH か？](https://qiita.com/suin/items/d17bdfc8dba086d36115)
   
### アドレス可読性（Addressability）

- やり取りされる全ての情報が一意なURIを持っており、URIにアクセスすることで、提供される情報を受信する。
   <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3057230/49c349d2-ba35-0b48-1a11-ca592b7e7000.png" width="500">

### 接続性（Connectability）
- やり取りする情報の内部に、別の情報や状態へのハイパーリンクを含めることができる。
    - RESTfulなシステム同士なら円滑に連携を行うことができる。

### ステートレス性（Stateless）
- ステート（状態）レス（ない）＝やり取りが１回ごとに完結する。
    - サーバはクライアントのセッション情報を保持しない。
    - APIが処理できる形でリクエストを投げる必要がある。

| メリット　| デメリット |
| ---- | ----|
|①セッション情報を保持する必要がないため、サーバ資源（メモリ、CPU等）を有効活用できる<br>②スケーラビリティのあるシステムになる(サーバを増やせば増やすほど、スループットが向上する)| ①各リクエストに処理に必要な情報を全て詰める必要があり、その結果トラフィックを圧迫する|

# 実装例（Java）
基本的な実装方法をまとめる。
## レスポンス側
①リクエストに対するレスポンス用のコントローラーを作成
```java:RestResponseController.java
@RestController // ※1
public class RestResponseController{
  
    @GetMapping(value = "/systemsv1/get/user-data", produces = "application/json; charset=utf-8") // ※2
    public List<UserData> ユーザ情報取得(@ModelAttribute UserDataForm form, Model model){
        
    	List<UserData> userDataList = 返却するユーザ情報リスト;

        return userInfo;
    }
}
```
※1　`@Controller`と`@ResponseBody`を合わせたアノテーション。
　 　 `@ResponseBody`はReturnオブジェクトのHttpResponseyへの自動シリアライゼーションを可能とする。
※2　value：URIを指定、produces：データの形式を指定（指定なしの場合はJSON形式となる）

## リクエスト側
①情報提供リクエストを送るコントローラーを作成
②データを受け取るためのBeanを用意
```java:RestRequestController.java
@Controller
public class RestRequestController{
  
    @GetMapping(value = "/userlist", produces = "application/json; charset=utf-8") // ※1
    public List<UserData> ユーザ情報取得(@ModelAttribute UserDataForm form, Model model){

        String url = "http://アプリURL/systemsv1/get/user-data"; // ※2
        
    	ResponseEntity<List<UserData>> response = restTemplate
            .exchange(url, HttpMethod.GET, null, new ParameterizedTypeReference<List<UserData>>(){
            });
        List<UserData> userData = response.getBody(); // ※3

        /* 省略 */
        /* 必要に応じ、取得したデータリストを加工・利用 */
        
        return "userListPage";
    }
}
```
※1　UTF-8のJSON形式で受け取る指定
※2 直アクセス（URLを直接叩く）すると、該当データがJSON形式で表示される
※3 レスポンス側と同じ変数名のBeanを用意しておく（必要な情報の項目だけでOK）

## 注意点
1. レスポンス側、リクエスト側のURIが一致していること
1. リクエストの回数を減らし、かつ、レスポンス側で問題が発生してもリクエスト側アプリに影響がないようにすると良い
    - レスポンス側のシステムが停止＝リクエスト側のシステムも停止するような作りは避ける

## 取得データの例
```java:レスポンス側のBean.java
public class UserData{
    private String userId;
    private String lastName;
    private String firstName;
}
```

```javascript:取得データ
userId:     "12345678"
lastName:   "日本"
firstName:  "太郎"
```
※JSONの項目名とリクエスト側でデータを受け取る際のBeanの変数名を一致させることで、JSONからBeanに変換してデータを受け取ることができる。

## 参考サイト
- [REST APIとは？ざっくりと理解してみる【初心者向け】](https://tech.012grp.co.jp/entry/rest_api_basics)
- [PUT か POST か PATCH か？](https://qiita.com/suin/items/d17bdfc8dba086d36115)