はじめに
Spring Bootを使用してREST APIを開発する際、エラーハンドリングの方法として@RestControllerAdvice
を使用したエラーハンドリングの方法を紹介します
@RestControllerAdvice
とは?
@RestControllerAdvice
は、Spring BootにおいてRESTコントローラー専用の例外処理を行うためのアノテーションです。このアノテーションを使用することで、アプリケーション全体で発生する例外を一元管理し、カスタマイズされたエラーレスポンスを返すことができます。
基本的な使い方
まずはハンドリングさせたいカスタム例外クラスを作成します。
class ResourceNotFoundException(message: String = "Resource not found") : RuntimeException(message)
デフォルト引数として "Resource not found"の文字列を入れていますが
呼び出し時に適切な文言へ変更します。
次に@RestControllerAdvice
アノテーションを使用して、グローバルな例外ハンドラを作成します。
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.ExceptionHandler
import org.springframework.web.bind.annotation.RestControllerAdvice
@RestControllerAdvice
class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException::class)
fun handleResourceNotFoundException(ex: ResourceNotFoundException): ResponseEntity<String> {
return ResponseEntity(ex.message, HttpStatus.NOT_FOUND)
}
}
あとはアプリケーションの任意の場所から
自分で定義したカスタム例外クラスをスローすると@RestControllerAdvice
がインターセプトして
定義されたresponseを返してくれます。
controllerで呼び出すと以下のようになります。
@RestController
class SampleController {
@GetMapping("/resource/{id}")
fun getResource(@PathVariable id: String): Resource {
if (id == "not_found") {
throw ResourceNotFoundException("Resource with ID $id not found")
}
return Resource(id, "Sample Resource")
}
}
controllerだけではなくてその先のservice、repositoryなどでエラーをスローしても
インターセプトしてエラーレスポンスを返してくれるので安心してください。
以下ChatGPTが教えてくれたメリデメです。
@RestControllerAdvice
のメリット
- 一元管理
例外処理を一箇所に集約することで、コードの可読性とメンテナンス性が向上します。
各コントローラーで個別に例外処理を記述する必要がなくなります。 - 一貫性
全ての例外に対して一貫したレスポンスを返すことができます。これにより、クライアント側のエラーハンドリングが容易になります。 - 再利用性
一度設定したグローバル例外ハンドラーは、全てのコントローラーで再利用できます。新しいコントローラーを追加する際に特別な設定をする必要がありません。 - コードの簡潔さ
コントローラーのコードが簡潔になり、本来のビジネスロジックに集中することができます。
@RestControllerAdvice
のデメリット
- 特定のコントローラーに対するカスタマイズが難しい
全体的なエラーハンドリングが一元化されるため、特定のコントローラーやメソッドに対するカスタムエラーハンドリングが難しくなる場合があります。 - 複雑なエラーハンドリングロジック
非常に複雑なエラーハンドリングロジックを必要とする場合、グローバルな例外ハンドラーが肥大化し、管理が難しくなる可能性があります。 - 予期しない影響
新しい例外ハンドラーを追加した際に、他のコントローラーや機能に予期しない影響を与える可能性があります。特に大規模なアプリケーションでは注意が必要です。 - デバッグが難しい
エラーがグローバルハンドラーでキャッチされるため、特定のコントローラーやメソッドで発生したエラーの原因を特定するのが難しくなることがあります。 - まとめ
serviceでスローしたエラーをcontrollerでcatchしてエラーレスポンスを返すっていう煩わしい処理を記述しなくていいのが便利ですね
積極的に使っていきたいと思います