REST APIでの例外処理の考え方!Spring MVCとSpring Bootで学ぶJSONエラーレスポンス設計入門
新人
「Spring MVCでREST APIを作り始めたんですが、エラーが起きたときに何を返せばいいのか分からなくなってきました……」
先輩
「画面遷移がない分、REST APIでは例外処理の考え方が少し変わりますね。」
新人
「これまではエラー画面に遷移していたんですが、JSONを返す場合はどう設計すればいいんでしょうか?」
先輩
「その疑問はとても大切です。REST APIでは、例外処理そのものがAPI設計の一部になります。」
1. REST APIにおける例外処理とは何か
REST APIにおける例外処理とは、サーバ側で何らかの問題が発生したときに、 その状況をクライアントへ分かりやすく伝えるための仕組みです。 Spring MVC REST API 例外処理 では、画面に遷移するのではなく、 処理結果としてデータそのものを返す点が大きな特徴になります。
従来のWebアプリケーションでは、入力エラーやシステムエラーが起きた場合、 専用のエラー画面へ遷移させるのが一般的でした。 一方、REST APIでは画面を持たないため、 「どのようなエラーが起きたのか」をJSON形式のデータとして返します。
つまり、REST APIにおけるエラーとは、 画面表示の問題ではなく「通信結果の一部」として扱われます。 この考え方を理解しないまま実装を進めると、 エラー時の挙動がバラバラになり、 クライアント側で扱いづらいAPIになってしまいます。
Spring MVCとSpring Bootを使ったREST API開発では、 例外処理を通してJSON エラーレスポンスをどのように設計するかが、 API全体の使いやすさを左右する重要なポイントになります。
@Controller
public class SampleApiController {
@GetMapping("/api/sample")
@ResponseBody
public String sample(@RequestParam String value) {
int num = Integer.parseInt(value);
return "ok";
}
}
このような処理で例外が発生した場合、 何も対策をしていなければ、 クライアントは原因が分からないレスポンスを受け取ることになります。 これを防ぐために、REST API専用の例外処理設計が必要になります。
2. なぜREST APIでは例外処理の設計が重要なのか
REST APIでは、例外処理がそのままAPIの仕様になります。 どのようなエラーが、どの形式で返ってくるのかは、 クライアント側の実装に直接影響を与えます。 そのため、Spring MVC REST API 例外処理 を設計する際には、 「とりあえず動けばよい」という考え方は通用しません。
例えば、入力値が不正だった場合と、 サーバ内部で想定外のエラーが起きた場合では、 本来返すべき情報は異なります。 それにもかかわらず、すべて同じ内容のJSONを返してしまうと、 クライアントは適切な処理を行うことができません。
また、REST APIでは複数の画面やシステムから同じAPIが呼び出されることが多く、 エラーレスポンスの形式が統一されていないと、 保守や拡張が難しくなります。 ここで重要になるのが、JSON エラーレスポンス を事前に設計するという考え方です。
Spring Bootを使った開発では、例外が発生したときの挙動を フレームワークに任せることもできますが、 それだけでは実務に耐えられるAPIにはなりません。 Spring MVCの仕組みを理解したうえで、 「どの例外を、どの情報として返すのか」を明確にする必要があります。
@ControllerAdvice
public class ApiExceptionHandler {
@ExceptionHandler(NumberFormatException.class)
@ResponseBody
public Map<String, String> handleNumberError() {
Map<String, String> error = new HashMap<>();
error.put("message", "数値の形式が正しくありません");
return error;
}
}
このように、REST APIでは例外処理そのものがAPI設計の一部になります。 画面遷移中心の考え方から一歩進み、 データとしてエラーを返す設計に慣れることが、 Spring MVCとSpring Bootを使ったAPI開発では欠かせません。
3. Spring MVCにおける例外発生の流れ
Spring MVC 例外処理 設計 を理解するためには、 まず「例外がいつ発生し、どこで捕まえられるのか」という流れを 頭の中でイメージできるようになることが重要です。 REST APIであっても、基本的な例外発生の流れは通常のWebアプリケーションと変わりません。
リクエストが送信されると、Spring MVCは対応する @Controller のメソッドを探し、 そのメソッドを実行します。 ここで、パラメータの変換やビジネスロジックの処理中に問題が起きると、 例外が発生します。 この時点では、まだJSONレスポンスは返っていません。
例外が発生すると、Spring MVCはその例外を呼び出し元へ戻しながら、 「この例外を処理できる仕組みが用意されているか」を探します。 まずはコントローラ自身に @ExceptionHandler が定義されていないかを確認し、 見つからなければ、次の候補へと処理が移っていきます。
REST API エラーハンドリング を意識した設計では、 この「例外がどこまで伝わり、どこで捕まるのか」を把握しておくことが欠かせません。 例外が捕まらないまま最後まで到達すると、 フレームワーク任せのレスポンスが返ってしまい、 APIとして一貫性のないエラー応答になる可能性があります。
4. @ExceptionHandler を使った基本的なREST API例外処理
Spring MVCでは、@ExceptionHandler を使うことで、 コントローラ内で発生した例外を捕まえ、 独自のレスポンスを返すことができます。 これは REST APIにおいても基本となる仕組みです。
@Controller を前提としたREST APIでは、 画面名ではなくデータを返す必要があるため、 @ResponseBody を併用してJSON形式のレスポンスを返します。 この書き方は、@RestController を使わない場合の基本形になります。
@Controller
public class SimpleApiController {
@GetMapping("/api/number")
@ResponseBody
public Map<String, Object> number(@RequestParam String value) {
int num = Integer.parseInt(value);
Map<String, Object> result = new HashMap<>();
result.put("result", num);
return result;
}
@ExceptionHandler(NumberFormatException.class)
@ResponseBody
public Map<String, String> handleNumberException() {
Map<String, String> error = new HashMap<>();
error.put("error", "数値に変換できません");
return error;
}
}
この例では、数値変換に失敗した場合に、 JSON形式のエラーメッセージを返すようになっています。 REST APIとして見ると、正常時もエラー時も「データが返る」という点が共通しています。
ただし、@ExceptionHandler には限界もあります。 この方法では、同じ例外処理を別のコントローラでも使いたい場合、 同じコードを何度も書く必要が出てきます。 コントローラの数が増えるほど、 例外処理が分散して管理しづらくなる点がデメリットです。
Spring MVC 例外処理 設計 では、 「まずは @ExceptionHandler で流れを理解する」 「共通化が必要になったら次の仕組みを考える」 という段階的な学習がとても重要になります。
5. JSON形式でエラーレスポンスを返す設計の考え方
REST APIでJSON形式のエラーレスポンスを返す理由は、 クライアントがエラー内容を正確に判断できるようにするためです。 単なる文字列だけではなく、 構造を持ったデータとして返すことで、 呼び出し元の処理が安定します。
JSON エラーレスポンス の設計で重要なのは、 「何が起きたのか」を最低限伝えられる情報を用意することです。 例えば、エラーメッセージだけでなく、 エラーの種類を表すコードや、 入力ミスなのかシステムエラーなのかを区別できる情報があると、 実務では非常に扱いやすくなります。
ただし、最初から複雑な設計を目指す必要はありません。 初心者のうちは、 メッセージをJSONで返すことに慣れるだけでも十分です。 大切なのは、画面遷移と同じ感覚で考えないことです。
@Controller
public class JsonErrorController {
@GetMapping("/api/check")
@ResponseBody
public Map<String, String> check(@RequestParam String text) {
if (text.isEmpty()) {
throw new IllegalArgumentException();
}
Map<String, String> result = new HashMap<>();
result.put("status", "ok");
return result;
}
@ExceptionHandler(IllegalArgumentException.class)
@ResponseBody
public Map<String, String> handleIllegalArgument() {
Map<String, String> error = new HashMap<>();
error.put("message", "入力値が不正です");
return error;
}
}
このような設計にしておくと、 REST API エラーハンドリング の考え方が自然と身についてきます。 正常系と異常系のレスポンスが明確に分かれ、 APIの利用者にとっても理解しやすい構成になります。
Spring MVCとSpring Bootを使ったREST API開発では、 例外処理を「後付けの対応」にしないことが重要です。 JSON形式でエラーレスポンスを返すという前提を持って設計することで、 API全体の品質と保守性が大きく向上します。
6. @ControllerAdvice を使ったREST API向け例外処理の共通化
REST APIの数が増えてくると、各コントローラに書いた @ExceptionHandler が少しずつ重複し始めます。 これは Spring MVC 例外処理 設計 において、 次の段階へ進むサインとも言えます。 ここで登場するのが @ControllerAdvice です。
@ControllerAdvice は、複数の @Controller に共通する例外処理を 一つのクラスにまとめるための仕組みです。 REST APIの場合でも考え方は同じで、 例外が発生したときに返す JSON エラーレスポンス を 共通ルールとして管理できるようになります。
処理の流れとしては、コントローラ内で例外が発生すると、 Spring MVC がまずコントローラ自身の @ExceptionHandler を探します。 見つからなかった場合、次に @ControllerAdvice が付いたクラスが参照され、 対応する例外処理が実行されます。 この流れを理解しておくことが、 @ControllerAdvice REST API 設計の第一歩になります。
@ControllerAdvice
public class GlobalApiExceptionHandler {
@ExceptionHandler(NumberFormatException.class)
@ResponseBody
public Map<String, String> handleNumberFormat() {
Map<String, String> error = new HashMap<>();
error.put("message", "数値の形式が正しくありません");
return error;
}
}
このように共通クラスを用意することで、 コントローラ側から例外処理のコードを取り除くことができます。 REST APIの処理本体と、エラーハンドリングの責務が分離され、 コード全体の見通しが良くなります。
ただし注意点もあります。 @ControllerAdvice にすべての例外を集約しすぎると、 「どのAPIで、なぜこのエラーが返っているのか」が 分かりにくくなることがあります。 共通化は便利ですが、必要な範囲にとどめる意識が重要です。
7. JSONエラーレスポンス設計で気をつけるポイント
Spring Boot JSON エラー設計 を考える際に最も大切なのは、 クライアントがそのエラーを正しく扱えるかどうかです。 単にエラーメッセージを返すだけでは、 実務では情報が不足するケースが多くあります。
JSONエラーレスポンスには、 最低限「何が起きたのか」が分かる情報を含める必要があります。 例えば、入力値が原因なのか、 サーバ内部の問題なのかが分かるだけでも、 APIの使いやすさは大きく変わります。
一方で、最初から多くの項目を詰め込みすぎるのも避けるべきです。 初心者の段階では、 メッセージと簡単な種別情報を返すだけでも十分です。 重要なのは、すべてのAPIで同じ形式を守ることです。
@ControllerAdvice
public class JsonErrorAdvice {
@ExceptionHandler(IllegalArgumentException.class)
@ResponseBody
public Map<String, Object> handleIllegalArgument() {
Map<String, Object> error = new HashMap<>();
error.put("type", "input_error");
error.put("message", "入力内容に誤りがあります");
return error;
}
}
このように、JSONエラーレスポンスに簡単な構造を持たせることで、 REST API エラーハンドリング が整理されます。 正常系と異常系が明確に分かれ、 APIを利用する側にとっても理解しやすい設計になります。
共通化を進める際には、 「すべて同じエラー形式で返すべきか」 「一部のAPIでは個別対応が必要か」 といった視点を持つことが大切です。 共通化しすぎない設計こそが、 長く使われるAPIを作るポイントになります。
8. 実務でのREST API例外処理の考え方と次に学ぶべき内容
実務でのREST API例外処理は、 いきなり完璧な設計を目指すものではありません。 最初は @ExceptionHandler で基本を押さえ、 重複が見えてきた段階で @ControllerAdvice による共通化を行う、 という流れが一般的です。
また、実務では例外処理は単体で考えられるものではなく、 ログ出力や監視とも密接に関係しています。 APIでエラーが発生したとき、 利用者向けには簡潔なJSONを返しつつ、 内部では原因を追跡できる情報を残す設計が求められます。
そのため、REST APIの例外処理を学んだ次のステップとしては、 ログ設計やエラーコード設計に目を向けるのがおすすめです。 どのエラーにどのコードを割り当てるのか、 どの情報をログに残すのかを考えることで、 API全体の品質が一段階向上します。
Spring MVCとSpring Bootを使ったREST API開発では、 例外処理は単なるエラー対策ではなく、 設計力を鍛えるための重要なテーマです。 JSONエラーレスポンス設計を起点に、 より実務に近い設計の考え方へと 学習を広げていくことが次の目標になります。