はじめに
研修期間中は、リクエストごとにURLを変えていましたが、どうやらREST APIってのがあるらしい、、
ということで、簡単にまとめてみました。
※誤りありましたら、ご指摘いただけますと幸いです。
REST APIとは
RESTと呼ばれる(Representational State Transfer)、Webサービスの設計におけるアーキテクチャスタイルの一つをもとに設計されたAPIを指します。
RESTでは、次に挙げる6つの原則が定められています。
-
クライアント-サーバーアーキテクチャ(Client-Server Architecture)
クライアントとサーバーの役割を明確に分けることによって、両者の独立した開発・運用を可能にします。 -
ステートレス(Statelessness)
クライアントから送られる各リクエストには、必要な情報が全て含まれており、サーバーはリクエスト間でクライアントの状態を保持しません。(クライアントからのリクエストはサーバーの状態に依存しないということ)これにより、スケーラビリティとシステムの信頼性が向上します。 -
キャッシュ可能(Cacheable)
適切なHTTPヘッダー(例えばCache-Control)を使って、レスポンスのキャッシュ可能性をクライアントに通知します。これにより、通信におけるデータ量が抑えられ、ネットワークの負荷が下がります。 -
統一インターフェース(Uniform Interface)
予め決められた方法でデータのやり取りを行うことを指します。リソースに対する操作は、 HTTPメソッド (GET, POST, PUT, DELETE等)を通じて行ったり、リソースは様々な形式(JSON, XMLなど)で表現され、クライアントはこれらの形式でリソースを理解します。 -
レイヤードシステム(Layered System)
レイヤードアーキテクチャとも呼ばれ、システムは複数の階層に分離して構築され、各階層は独自の役割を持ちます。 -
コードオンデマンド(Code on Demand, optional)
サーバーはクライアントに、クライアント側で実行できるコード(現在はJavaScriptが多い)を送信し、クライアント側の実装コストを下げます。
ちなみにこの原則のみはあくまで任意となっています。
コードの比較
実際のコードを見てみましょう。
今回は、テンプレートエンジン(Thymeleaf)を使用してHTMLを返す実装と、REST APIを用いた実装の比較になります。
パッケージ指定とインポート文は省略しています
HTMLを返すコントローラクラス
@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を基にしたコントローラクラス
@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)方式で送られるデータはこんな感じ。
{
"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について調べてみた
「RESTとはなんぞや?」を4原則から考えてみる
REST APIとは?6つのルールを初心者向けにわかりやすく解説!
REST APIとは何か?初心者にもわかりやすく解説します!