はじめに
Spring Boot で API を作っていると、
例外が発生したときにどう返すか がとても重要になります。
- try-catch を Controller に書くべき?
- エラーのレスポンス形式はどう統一する?
- バリデーションエラーはどう扱う?
こういった疑問を解決してくれるのが
@ControllerAdvice と @ExceptionHandler です。
この記事では、例外ハンドリングの基本を
やさしく・実務寄り で整理していきます。
まずはコードから見ていきましょう。
ControllerAdvice とは
一言でいうと、
「アプリ全体の例外処理を一箇所にまとめる仕組み」
です。
- Controller ごとに try-catch を書かなくていい
- エラーレスポンスを統一できる
- バリデーションエラーもまとめて処理できる
API の品質が一気に上がります。
基本のコード例
例外クラス
public class UserNotFoundException extends RuntimeException {
public UserNotFoundException(String message) {
super(message);
}
}ControllerAdvice
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<ErrorResponse> handleUserNotFound(UserNotFoundException e) {
ErrorResponse error = new ErrorResponse("USER_NOT_FOUND", e.getMessage());
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
}
}ErrorResponse DTO
public class ErrorResponse {
private String code;
private String message;
}これで、
UserNotFoundException が発生したら 404 を返す
という仕組みが完成します。
ControllerAdvice の役割を具体的に整理する
例外処理を一箇所にまとめる
Controller に try-catch を書く必要がなくなります。
throw new UserNotFoundException("ユーザーが見つかりません");Service で例外を投げるだけで OK。
エラーレスポンスを統一できる
API のエラー形式がバラバラだと、 フロントエンドがとても困ります。
ControllerAdvice を使えば、 全 API のエラー形式を統一 できます。
例:
{
"code": "USER_NOT_FOUND",
"message": "ユーザーが見つかりません"
}バリデーションエラーをまとめて処理できる
@Valid のエラーは MethodArgumentNotValidException が発生します。
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleValidation(MethodArgumentNotValidException e) {
String message = e.getBindingResult().getFieldError().getDefaultMessage();
ErrorResponse error = new ErrorResponse("VALIDATION_ERROR", message);
return ResponseEntity.badRequest().body(error);
}これで、 バリデーションエラーも統一された形式で返せる ようになります。
予期しない例外もキャッチできる
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleException(Exception e) {
ErrorResponse error = new ErrorResponse("INTERNAL_ERROR", "予期しないエラーが発生しました");
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
}実務でよくあるアンチパターン
Controller に try-catch を書きまくる
→ コードが読みにくくなる
→ 例外処理が散らばる
→ レスポンス形式がバラバラになる
例外を握りつぶしてしまう
try {
...
} catch (Exception e) {
return null;
}→ デバッグ不能になります。
エラー形式が API ごとに違う
→ フロントが地獄を見る
ControllerAdvice をもっと活かすポイント
エラーコードを定義する
"USER_NOT_FOUND"
"VALIDATION_ERROR"
"INTERNAL_ERROR"ログを適切に出す
- 業務エラー → warn
- システムエラー → error
ResponseEntity と組み合わせる
ステータスコードを明確にできます。
まとめ
ControllerAdvice は、
「例外処理を一箇所にまとめ、API の品質を上げる仕組み」
です。
- try-catch を Controller に書かなくていい
- エラーレスポンスを統一できる
- バリデーションエラーもまとめて処理
- 予期しない例外もキャッチ
- Service で例外を投げるだけで OK
難しく聞こえますが、
「例外処理を一箇所に集めるための仕組み」
と理解できれば十分です。

ControllerAdvice を理解すると、
API のエラー処理が一気にきれいになります。
例外を“どこで投げて、どこで受け取るか”が整理されるだけで、
設計も保守もぐっと楽になります。
あなたの開発が、今日より少しだけ楽になりますように。

困ったときに全部受け止めてくれる場所…
ControllerAdvice さん、やさしいね。

コメント