SpringBootの例外ハンドリング
概要
SpringBootにおいては、SpringMVCの機能を用いた例外ハンドリングやSpringBootのAutoConfigurationと組み込みサーバーを利用した例外ハンドリングなど複数の方法で例外を取り扱うことができる。
公式リファレンスで述べられているが、ハンドリングが可能な範囲や仕組みが若干わかりにくいので主要な方法をまとめる。
例外ハンドリングの方法
一覧
機能名 | レイヤ |
---|---|
HandlerExceptionResolver | SpringMVC |
ErrorPage | SpringBoot |
ErrorController | SpringBoot |
HandlerExcepitonResolver
HandlerExceptionResolver
はSpringMVCの機能を利用した例外ハンドリングの方法である。
SpringMVCの機能を利用しているため、FilterやViewで例外が生じた場合はハンドリングできない。
HandlerExceptionResolver
は下記に示す複数の実装クラスがデフォルトで用意されている。
なお、下記の表において有効/無効はSpringBootのデフォルト設定で有効か無効かを示し、上に来るExceptionResolverが優先される。
クラス名 | 有効/無効 | 機能 |
---|---|---|
ExceptionHandlerExceptionResolver | 有効 | @ExceptionHandlerが付与されたメソッドにより例外ハンドリングを行う |
ResponseStatusExceptionResolver | 有効 | @ResponseStatusが付与されている例外クラスが発生した際にハンドリングを行う |
DefaultHandlerExceptionResolver | 有効 | SpringMVCで定義されている例外クラスのハンドリングを行う |
SimpleMappingExceptionResolver | 無効 | 例外クラスとViewを直接マッピングする |
下記に一番オーソドックスなExceptionHandlerExceptionResolver
による例外ハンドリングの方法を示す。
ExceptionHandlerExceptionResolverによるハンドリング
例外発生時に、発生した例外クラスのメタ情報が付与された@ExceptionHandlerアノテーションを持つメソッドを走査し、処理が移譲される。
@ExceptionHandlerを付与したメソッドは下記に示すように@Controllerもしくは@ControllerAdviceを付与したクラス内に定義できる。
@Controller
@RequestMapping("web")
public class ThrowExceptionController {
@GetMapping("original")
public void throwOriginalException() {
throw new OriginalWebException("thrown in ThrowExceptionController");
}
@ExceptionHandler(OriginalWebException.class)
public String handleOriginalWebException(OriginalWebException exception) {
return "OriginalWebException.html";
}
}
@ControllerAdvice
public class ThrowExceptionController {
@ExceptionHandler(OriginalWebException.class)
public String handleOriginalWebException(OriginalWebException exception) {
return "OriginalWebException.html";
}
}
@Controllerの場合、例外ハンドリングが可能なのは同一Controllerで発生した例外だけだが、@ControllerAdviceの場合は全てのControllerを横断的にハンドリングできる。
また、@Controllerと@ControllerAdviceどちらでもハンドリング可能な場合は@Controllerに付与された方が優先される。
ErrorPage
SpringBootにおけるErrorPageは従来のSpringFWのWeb.xmlで定義していたErrorPage要素とほぼ等しい。
ErrorPageはステータスコードか例外クラスとパスをマッピングし、ハンドリングを行えるようにする。
概略図を下記に示す。
ErrorPageの登録の仕方は下記に示すようにErrorPageRegistrarの実装クラスを作成することで行える。
@Configuration
public class AddErrorPage implements ErrorPageRegistrar {
@Override
public void registerErrorPages(ErrorPageRegistry registry) {
registry.addErrorPages(new ErrorPage(exception, path));
// new ErrorPage(HttpStatusCode, path)でも可能
}
}
ErrorController
ErrorControllerはSpringBootによって提供される例外ハンドリングの手法であり、SpringBootの例外ハンドリングの中で最も一般的にとられる手法である。
概略図を下記に示す。
SpringBootのアプリケーションで生じる例外がハンドリングされなかった場合、上述のErrorPage機能によって全て/error
のパスへディスパッチされることになっている。
/error
はデフォルトではBasicErrorController
クラスがマッピングされており、そこでハンドリングが行われる。
BasicErrorController
では、ハンドリングはリクエストヘッダーによってHTMLかJSONを返却する。
HTMLの場合はWhiteLabelErrorPage
が返却され、返却される内容はErrorAttributes
によって規定されている。
JSONの場合はErrorAttributes
が返却される。
ErrorController
によるハンドリング方法をカスタマイズする場合はErrorController
の実装クラスを作成する。
また、返却内容自体をカスタマイズする場合はErrorAttributes
クラスを実装する。
まとめ
SpringBootアプリケーションにおける例外ハンドリングは、基本的にはErrorController
を用い、より細かいハンドリングを行いたい場合はHandlerExceptionResolver
を用いると良い。