web-dev-qa-db-ja.com

Spring MVCで例外を処理するための推奨される方法は何ですか

私は、アプリケーションをいくつか呼び出してデータをフェッチするSpringアプリケーションを持っています。コントローラ層とサービス層の間にデータ層があります。

Controller (Request-Mapping) -> Data Layer -> Service Layer

基になるサービスからデータを取得しない場合は、例外をスローする予定です。私の質問は、ここで採用するベストプラクティスに関するものです。

  1. DataProvider(データレイヤー)を作成し、コントローラーが例外をスローして、Tomcatにweb.xml経由で処理させる必要がありますか?

  2. データレイヤー自体で例外をキャッチし、それをログに記録して、コントローラーに例外を伝播しないでください。

具体的には、コントローラを「throw CustomException」としてマークするのは良いことでしょうか?

3
Abhigyan Mehra

コントローラーハンドラーメソッドから例外をスローすることは悪いことだという意見に反して、そうすることをお勧めします。理由は次のとおりです。

  1. それは多くの定型コードを排除します。コントローラーのほとんどすべてのトライキャッチは同じで、頻繁にある場所から別の場所にコピーアンドペーストされます。これにより、コードメンテナンスの負担が増加し、コントローラーと例外階層間の結合が増加します。

  2. 例外を正しく処理する方法は他にもあります。最善の解決策は、特定のタイプの例外をHTTP応答コードに変換するグローバル例外ハンドラーを用意することです。例えば。データベースクエリまたはリモート呼び出しがタイムアウトで失敗した場合は、HTTP 503に変換できます。リポジトリがObjectNotFoundExceptionをスローした場合は、HTTP 404を返すことができます。検証が失敗した場合は、HTTP 400で応答します。コントローラー固有のハンドラーをいくつか用意することもできます。特定のケース(まれな状況が異なります)。

とはいえ、メソッドシグネチャに「例外をスローする」必要があるという意味ではありません。レイヤードアーキテクチャでは、コントローラーなどの上位レイヤーのオブジェクトは、カプセル化に違反するため、低レベルの例外(JDBCドライバーなど)を期待できません。レイヤーごとに別の例外階層があり、そのレイヤーに固有のセマンティクスがあり、例外変換が必要です(通常はラップによって行われます)。たとえば、RepositoryのConstraintViolationExceptionにより、サービスでInvalidServiceRequestExceptionが発生し、例外ハンドラーによってHTTP 400に変換される場合があります。

5
Ivan Gammel

@ ResponseStatus、@ ExceptionHandler、@ ControllerAdviceアノテーションを使用して、可能な場合はコントローラーメソッドで例外を明示的に処理できます。詳細については、次を参照してください: Spring MVCでの例外処理

0
Piyush Desai