例外

リクエストのマッピング中に例外が発生した場合、またはリクエストハンドラー(@Controller など)からスローされた場合、DispatcherServlet は HandlerExceptionResolver Bean のチェーンに委譲して、例外を解決し、代替処理(通常はエラーレスポンス)を提供します。

次の表に、使用可能な HandlerExceptionResolver 実装を示します。

表 1: HandlerExceptionResolver の実装
HandlerExceptionResolver 説明

SimpleMappingExceptionResolver

例外クラス名とエラービュー名の間のマッピング。ブラウザーアプリケーションでエラーページをレンダリングできます。

DefaultHandlerExceptionResolver (Javadoc)

Spring MVC によって発生した例外を解決し、HTTP ステータスコードにマップします。代替の ResponseEntityExceptionHandler およびエラーレスポンスも参照してください。

ResponseStatusExceptionResolver

@ResponseStatus アノテーションを使用して例外を解決し、アノテーションの値に基づいて HTTP ステータスコードにマッピングします。

ExceptionHandlerExceptionResolver

@Controller または @ControllerAdvice クラスの @ExceptionHandler メソッドを呼び出すことにより、例外を解決します。@ExceptionHandler メソッドを参照してください。

リゾルバーのチェーン

Spring 構成で複数の HandlerExceptionResolver Bean を宣言し、必要に応じて order プロパティを設定することにより、例外リゾルバーチェーンを形成できます。順序プロパティが高いほど、例外リゾルバーが後から配置されます。

HandlerExceptionResolver の契約は、以下を返すことができることを指定しています。

  • エラービューを指す ModelAndView

  • リゾルバー内で例外が処理された場合、空の ModelAndView

  • null は、後続のリゾルバーが試行するために例外が未解決のままである場合、および例外が最後に残っている場合、サーブレットコンテナーまでバブルアップすることが許可されます。

MVC 構成は、デフォルトの Spring MVC 例外、@ResponseStatus アノテーション付き例外、および @ExceptionHandler メソッドのサポート用の組み込みリゾルバーを自動的に宣言します。そのリストをカスタマイズするか、置き換えることができます。

コンテナーエラーページ

例外が HandlerExceptionResolver によって未解決のままであり、伝播するために残されている場合、またはレスポンスステータスがエラーステータス(4xx、5xx)に設定されている場合、サーブレットコンテナーは HTML でデフォルトのエラーページをレンダリングできます。コンテナーのデフォルトのエラーページをカスタマイズするために、web.xml でエラーページマッピングを宣言できます。次の例は、その方法を示しています。

<error-page>
	<location>/error</location>
</error-page>

前述の例では、例外がバブルアップするか、レスポンスにエラーステータスが含まれる場合、サーブレットコンテナーはコンテナー内で構成済みの URL(/error など)に対して ERROR ディスパッチを行います。次に、これは DispatcherServlet によって処理され、おそらく @Controller にマッピングされます。これは、次の例に示すように、モデルとともにエラービュー名を返すか、JSON レスポンスをレンダリングするために実装できます。

  • Java

  • Kotlin

@RestController
public class ErrorController {

	@RequestMapping(path = "/error")
	public Map<String, Object> handle(HttpServletRequest request) {
		Map<String, Object> map = new HashMap<>();
		map.put("status", request.getAttribute("jakarta.servlet.error.status_code"));
		map.put("reason", request.getAttribute("jakarta.servlet.error.message"));
		return map;
	}
}
@RestController
class ErrorController {

	@RequestMapping(path = ["/error"])
	fun handle(request: HttpServletRequest): Map<String, Any> {
		val map = HashMap<String, Any>()
		map["status"] = request.getAttribute("jakarta.servlet.error.status_code")
		map["reason"] = request.getAttribute("jakarta.servlet.error.message")
		return map
	}
}
サーブレット API は、Java でエラーページマッピングを作成する方法を提供しません。ただし、WebApplicationInitializer と最小限の web.xml の両方を使用できます。