2016-10-31 1 views
3

のマッピングはありません場合にのみ、私は以下のコントローラとexceptionHandlerのを持って呼び出されます:@ExceptionHandlerは、ばねウェブ-4.2.6を使用して例外

@ControllerAdvice 
public class ExceptionsHandler { 
    @ExceptionHandler(Exception.class) 
    public ResponseEntity<ErrorDTO> HandleDefaultException(Exception ex) { 
    ... 
    } 

    @ExceptionHandler(InternalError.class) 
    public ResponseEntity<ErrorDTO> HandleInternalError(InternalError ex) { 
    ... 
    } 
} 

@RestController 
@RequestMapping("/myController") 
public class MyController { 
    @RequestMapping(value = "/myAction", method = RequestMethod.POST) 
    public boolean myAction() { 
     throw new InternalError(""); 
    } 
} 

何らかの理由で、ExceptionsHandlerのHandleDefaultExceptionについて(例外のために.class)メソッドが呼び出されますが、HandleInternalError呼び出しの代わりにNestedServletException型は例外です。

デフォルトの呼び出しを削除すると、IntenalError呼び出しが適切なInternalError例外とともに呼び出されます。

ユーザーにとってより良いエクスペリエンスを実現するために、デフォルトのハンドラを使用することが重要であるため、デフォルトの呼び出しを削除したくありません。

私はここで何が欠けていますか?

EDIT:

どうやら私はそれを求めず、バネのウェブ-4.3.3を使用しています。なぜ私のGradle依存関係のツリーが正確にわからないのですか? http://pastebin.com/h6KXSyp2

+0

あなたは4.2.6を使用していますか?あなたが記述する振る舞いは、4.3+でしか動作しません。 –

答えて

4

Spring MVCは、バージョン4.3以上で説明した動作のみを示す必要があります。 this JIRA issueを参照してください。以前は、Spring MVCはThrowableの値を@ExceptionHandlerメソッドに公開しませんでした。 4.3以降


を参照してください、Spring MVCのは、それは、通常のExceptionHandlerExceptionResolverプロセスにさらされる、あなたのハンドラメソッドからスローされたThrowableをキャッチし、NestedServletExceptionでそれをラップします。

ここにそれがどのように動作するかの簡単な説明です:

  1. をチェックハンドラメソッドの@Controllerクラスがどの@ExceptionHandlerメソッドが含まれている場合。
  2. この場合、Exceptionタイプ(NestedServletExceptionを含む)を処理できるものを解決しようとします。可能であれば、それを使用します(複数の一致が見つかった場合はソートが行われます)。できない場合、Exceptionにはcauseが含まれていますが、アンラップして再度そのハンドラを検索しようとします。 causeThrowable(またはそのサブタイプのいずれか)になりました。
  3. そうでない場合。 @ControllerAdviceクラスをすべて取得し、Exceptionタイプ(NestedServletExceptionを含む)のハンドラを見つけようとします。可能であれば、それを使用します。できない場合、Exceptionにはcauseが含まれていますが、それをアンラップして、Throwableタイプで再試行します。

この例では、MyControllerInternalErrorをスローします。これはExceptionのサブクラスではないので、Spring MVCはNestedServletExceptionにラップします。

MyControllerには@ExceptionHandlerのメソッドがないため、Spring MVCはスキップします。 注釈付きクラスExceptionsHandlerがあるため、Spring MVCでチェックされます。@ExceptionHandler注釈付きHandleDefaultExceptionメソッドはExceptionを処理できるため、Spring MVCはNestedServletExceptionを処理するように選択します。

HandleDefaultExceptionを削除すると、Spring MVCはExceptionを処理できるものを見つけられません。次に、NestedServletExceptionのラップを解除し、そのcauseを確認します。それはそのInternalErrorを扱うことができるHandleInternalErrorを見つけるでしょう。

これは扱いやすい問題ではありません。いくつかのオプションがあります:

NestedServletExceptionを処理する@ExceptionHandlerを作成し、InternalErrorのチェックをしてください。

@ExceptionHandler(NestedServletException.class) 
public ResponseEntity<String> HandleNested(NestedServletException ex) { 
    Throwable cause = ex.getCause(); 
    if (cause instanceof InternalError) { 
     // deal with it 
    } else if (cause instanceof OtherError) { 
     // deal in some other way 
    } 
} 

あなたが処理したい異なるErrorまたはThrowableタイプの束がありますしない限り、これは問題ありません。 (Spring MVCはデフォルトで他の動作を行い、500エラーコードを返す可能性があります)

また、 Spring MVCが最初に@ExceptionHandlerメソッドの@Controller(または@RestController)クラスをチェックしているという事実です。 InternalError@ExceptionHandlerメソッドをコントローラに移動するだけです。

@RestController 
@RequestMapping("/myController") 
public class MyController { 
    @RequestMapping(value = "/myAction", method = RequestMethod.POST) 
    public boolean myAction() { 
     throw new InternalError(""); 
    } 

    @ExceptionHandler(value = InternalError.class) 
    public ResponseEntity<String> HandleInternalError(InternalError ex) { 
     ... 
    } 
} 

今、春が最初MyControllerNestedServletExceptionのハンドラを見つけることを試みます。何も見つからないので、NestedServletExceptionをアンラップし、InternalErrorを得ます。 InternalErrorのハンドラを見つけて、HandleInternalErrorを探します。

これは、複数のコントローラのハンドラメソッドがInternalErrorを投げる場合、それぞれに@ExceptionHandlerを追加する必要があるという欠点があります。これはまた利点かもしれません。あなたの処理ロジックは、エラーをスローするものに近いでしょう。

+0

どうやら私はspring-web-4.3.3を使っています。私は理由を理解していない、私のGradleの依存関係ツリーです:http://pastebin.com/h6KXSyp2 – Tsury

+0

私は4.3.3を使用していると仮定して、@ControllerAdviceで2つのクラスを作成することはできますか?特定の例外(InternalErrorなど) 1つはデフォルトの例外用で、特定の例外を持つものは最初に起動させますか? – Tsury

+0

私は、特定の例外に対して@Order(1)、一般的なものにOrder(2)を持つ2つの@ControllerAdviceクラスを作成しました。 – Tsury

関連する問題