初心者がREST APIについてまとめてみた。

## はじめに

  研修期間中は、リクエストごとにURLを変えていましたが、どうやらREST APIってのがあるらしい、、
  ということで、簡単にまとめてみました。
  
  ※誤りありましたら、ご指摘いただけますと幸いです。

## REST APIとは  
  RESTと呼ばれる（Representational State Transfer）、Webサービスの設計におけるアーキテクチャスタイルの一つをもとに設計されたAPIを指します。

  RESTでは、次に挙げる6つの原則が定められています。

  1. **クライアント-サーバーアーキテクチャ（Client-Server Architecture）**  
  クライアントとサーバーの役割を明確に分けることによって、両者の独立した開発・運用を可能にします。

  2. **ステートレス（Statelessness）**  
  クライアントから送られる各リクエストには、必要な情報が全て含まれており、サーバーはリクエスト間でクライアントの状態を保持しません。（クライアントからのリクエストはサーバーの状態に依存しないということ）これにより、スケーラビリティとシステムの信頼性が向上します。

  3. **キャッシュ可能（Cacheable）**  
  適切なHTTPヘッダー（例えばCache-Control）を使って、レスポンスのキャッシュ可能性をクライアントに通知します。これにより、通信におけるデータ量が抑えられ、ネットワークの負荷が下がります。

  4. **統一インターフェース（Uniform Interface）**  
    予め決められた方法でデータのやり取りを行うことを指します。リソースに対する操作は、 **HTTPメソッド** （GET, POST, PUT, DELETE等）を通じて行ったり、リソースは様々な形式（JSON, XMLなど）で表現され、クライアントはこれらの形式でリソースを理解します。

  5. **レイヤードシステム（Layered System）**
  レイヤードアーキテクチャとも呼ばれ、システムは複数の階層に分離して構築され、各階層は独自の役割を持ちます。

  6. **コードオンデマンド（Code on Demand, optional）**  
  サーバーはクライアントに、クライアント側で実行できるコード（現在はJavaScriptが多い）を送信し、クライアント側の実装コストを下げます。
  ちなみにこの原則のみはあくまで任意となっています。



## コードの比較
  実際のコードを見てみましょう。
  今回は、テンプレートエンジン（Thymeleaf）を使用してHTMLを返す実装と、REST APIを用いた実装の比較になります。

:::note warn
パッケージ指定とインポート文は省略しています
:::

### HTMLを返すコントローラクラス
```java:java
@Controller
@RequestMapping("/users")
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping
    public String getAllUsers(Model model) {
        List<User> users = userService.getAllUsers();
        model.addAttribute("users", users);
        return "user-list"; // Thymeleafテンプレート名（user-list.html）
    }

    @RequestMapping("/{id}")
    public String getUserById(@PathVariable Long id, Model model) {
        User user = userService.getUserById(id).orElse(null);
        model.addAttribute("user", user);
        return "user-detail"; // Thymeleafテンプレート名（user-detail.html）
    }

    @RequestMapping("/toCreate")
    public String showCreateUserForm(Model model) {
        model.addAttribute("user", new User());
        return "user-form"; // Thymeleafテンプレート名（user-form.html）
    }

    @RequestMapping("/create")
    public String createUser(@ModelAttribute User user, Model model) {
        userService.createUser(user);
        return "redirect:/users"; // ユーザーリストページにリダイレクト
    }

    @RequestMapping("/edit/{id}")
    public String showEditUserForm(@PathVariable Long id, Model model) {
        User user = userService.getUserById(id).orElse(null);
        if (user != null) {
            model.addAttribute("user", user);
            return "user-form"; // Thymeleafテンプレート名（user-form.html）
        } else {
            return "redirect:/users"; // ユーザーリストページにリダイレクト
        }
    }

    @RequestMapping("/update/{id}")
    public String updateUser(@PathVariable Long id, @ModelAttribute User user, Model model) {
        userService.updateUser(id, user);
        return "redirect:/users"; // ユーザーリストページにリダイレクト
    }

    @RequestMapping("/delete/{id}")
    public String deleteUser(@PathVariable Long id) {
        userService.deleteUser(id);
        return "redirect:/users"; // ユーザーリストページにリダイレクト
    }
}

```

### REST APIを基にしたコントローラクラス

```java:java
@RestController
@RequestMapping("/api/users")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping
    public List<User> getAllUsers() {
        return userService.getAllUsers();
    }

    @GetMapping("/{id}")
    public ResponseEntity<User> getUserById(@PathVariable Long id) {
        return userService.getUserById(id)
                .map(ResponseEntity::ok)
                .orElseGet(() -> ResponseEntity.notFound().build());
    }

    @PostMapping
    public ResponseEntity<User> createUser(@RequestBody User user) {
        User createdUser = userService.createUser(user);
        return ResponseEntity.ok(createdUser);
    }

    @PutMapping("/{id}")
    public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody User user) {
        return userService.updateUser(id, user)
                .map(ResponseEntity::ok)
                .orElseGet(() -> ResponseEntity.notFound().build());
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
        if (userService.deleteUser(id)) {
            return ResponseEntity.noContent().build();
        } else {
            return ResponseEntity.notFound().build();
        }
    }
}

```
  

## 違いについて

上記の2種類のコードの大きな違いを2点解説します。

### ①`@Controller`と`@RestController`

`@RestController` は、`@Controller`と`@ResponseBody`の組み合わせとして機能します。`@ResponseBody`が付与されると、メソッドの戻り値を **JSON** や **XML** などの形式にシリアライズします。

ちなみにJSON（JavaScript Object Notation）方式で送られるデータはこんな感じ。

```json:json
{
  "name": "山田太郎",
  "email": "yamada.tarou@example.com"
}
```
JSONはデータ記述言語のひとつであり、Java, PHP, Ruby, Python など、様々な言語間のデータ交換で使用されています。
  

### ②URLの対応付け
作成・取得・更新・削除を行うにあたって、前者では`@RequestMapping`を使用して、各処理とURLが紐づいていました。

しかし後者は、各処理が`@RequestMapping("/api/users")`というURLと、`@GetMapping`や`@PostMapping`等に紐づいています。

では、そのように処理を区別しているかというと、ここで登場するのが **HTTPリクエストメソッド** になります。

HTTPリクエストメソッドには「GET」なら取得、「POST」なら作成、「PUT」なら更新、「DELETE」なら削除のように、どのようなやり取りを行うか、という情報が含まれており、この情報を基に処理を決定する形になります。
  


## まとめ
  REST APIという共通の枠組みを用いて開発が行えることで、シンプルで理解しやすい開発が可能になります。

  API実装において、REST APIは主流になってきているので、もっと細かい部分もキャッチアップが必要だと感じました。

## 参考文献
[0からREST APIについて調べてみた](https://qiita.com/masato44gm/items/dffb8281536ad321fb08)
[「RESTとはなんぞや？」を４原則から考えてみる](https://qiita.com/185shingeki/items/ce01ee915504b8601193)
[REST APIとは？6つのルールを初心者向けにわかりやすく解説！](https://chmod774.com/rest-api/)
[REST APIとは何か？初心者にもわかりやすく解説します！](https://study-sec.com/rest-api/#REST_API-3)