Spring Bootの例外処理入門!初心者にもわかる基本と設計の考え方
Spring Bootを使ったWebアプリケーション開発を、 環境構築から実践まで一通り学びたい方には、 定評のある入門書が参考になります。
Spring Boot 3 プログラミング入門をAmazonで見る※ Amazon広告リンク
生徒
「Spring Bootでエラーが出たときに、ちゃんとしたメッセージを返す方法ってあるんですか?」
先生
「もちろんありますよ。Spring Bootでは例外処理をうまく設計することで、APIの信頼性やユーザー体験を向上させられます。」
生徒
「エラーメッセージを統一したり、共通の処理をしたりってできますか?」
先生
「では、例外処理の基本から、@ControllerAdviceや@ExceptionHandlerの使い方、そして設計のポイントまで詳しく解説していきましょう。」
1. Spring Bootの例外処理とは?
Spring Bootの例外処理とは、アプリケーション実行中に発生したエラー(例外)を適切にキャッチして、開発者が意図した形式でレスポンスやログを返すための仕組みです。
例えば、入力値が不正なときやデータが存在しないときなどに、ただの500エラーではなく、ユーザーにわかりやすいメッセージを返すために使われます。
2. @ExceptionHandlerによる基本的な例外処理
@ExceptionHandlerは、特定のコントローラ内で発生した例外をキャッチして処理するためのアノテーションです。
@Controller
public class SampleController {
@GetMapping("/error-test")
public String errorTest() {
throw new IllegalArgumentException("不正な入力です");
}
@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<String> handleIllegalArgument(IllegalArgumentException ex) {
return ResponseEntity.badRequest().body("エラー: " + ex.getMessage());
}
}
このように、特定の例外クラスに対して独自のレスポンスを返すことができます。ただし、複数のコントローラで同じ処理を書くのは大変なので、共通化の仕組みが必要になります。
3. @ControllerAdviceで共通の例外処理クラスを作成
Spring Bootでは、@ControllerAdviceを使ってアプリケーション全体の例外処理を一括で管理できます。API開発などでは特に役立ちます。
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<String> handleIllegalArgument(IllegalArgumentException ex) {
return ResponseEntity.badRequest().body("リクエストエラー: " + ex.getMessage());
}
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleException(Exception ex) {
return ResponseEntity.internalServerError().body("システムエラーが発生しました");
}
}
@ExceptionHandlerを複数定義すれば、例外の種類に応じたメッセージを分けることができます。これで例外処理の重複も減り、保守性が高まります。
Spring FrameworkやThymeleafを使った Webアプリ開発の全体像をやさしく理解したい人には、 この入門書が定番です。
Spring Framework超入門をAmazonで見る※ Amazon広告リンク
4. オリジナルの例外クラスを定義する
アプリケーション独自のエラー状態に対応するために、独自の例外クラスを作ることもよくあります。例えば、「データが見つからない」などのケースです。
public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String message) {
super(message);
}
}
そして、GlobalExceptionHandlerでこの例外をキャッチするようにします。
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<String> handleNotFound(ResourceNotFoundException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("データが見つかりません: " + ex.getMessage());
}
5. JSON形式でエラーレスポンスを返す設計
Spring BootでAPI開発をしている場合は、HTMLではなくJSON形式でエラーを返すことが一般的です。レスポンスボディに詳細な情報を含めると、フロントエンドとの連携がしやすくなります。
public class ErrorResponse {
private String message;
private String errorCode;
// コンストラクタ・getter・setter省略
}
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ErrorResponse> handleNotFound(ResourceNotFoundException ex) {
ErrorResponse error = new ErrorResponse();
error.setMessage("データが存在しません");
error.setErrorCode("404_NOT_FOUND");
return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
}
このような実装により、RESTfulなエラーハンドリングが可能になります。エラーコードを含めることで、クライアント側の処理分岐にも使えます。
6. バリデーションエラーの処理方法
@Validや@Validatedを使ったフォームバリデーションでは、MethodArgumentNotValidExceptionという例外が発生します。この例外も@ControllerAdviceで一括処理が可能です。
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleValidation(MethodArgumentNotValidException ex) {
String errorMessage = ex.getBindingResult().getAllErrors().get(0).getDefaultMessage();
ErrorResponse error = new ErrorResponse();
error.setMessage("入力エラー: " + errorMessage);
error.setErrorCode("400_VALIDATION");
return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
}
これにより、フォームのバリデーションエラーにも統一されたレスポンス形式を適用できます。
7. 設計指針:例外処理で意識すべきポイント
Spring Bootで例外処理を設計するときは、以下のポイントを意識すると、開発と保守がしやすくなります。
- 独自の例外クラスを使ってエラーの種類を明確にする
- JSONレスポンスにしてエラーコードを付ける
@ControllerAdviceで例外処理を集中管理する- ログ出力とユーザー向けメッセージを分離する
- 開発初期段階から例外処理のルールを決めておく
例外処理は単なるエラー回避の仕組みではなく、アプリの品質やユーザビリティに直結する重要な設計要素です。