API例外処理-HandlerExceptionResolver

4598 ワード

API異常処理


異常が発生し、サーブレットからWASに異常が伝達されると仮定すると、HTTPステータスコードは500として設計される.このとき発生する例外により、400、404などの他のステータスコードも処理したい.
例)
例えば、IllegalArgumentExceptionが処理できないためにコントローラから飛び出した場合は、HTTPステータスコードを400に処理したい.どうしようかな?
@RestController
public class ApiExceptionController {
    @GetMapping("/api/members/{id}")
    public MemberDto getMember(@PathVariable("id") String id) {
        if ("ex".equals(id)) {
            throw new RuntimeException("잘못된 사용자");
        }
        if ("bad".equals(id)) {
            throw new IllegalArgumentException("잘못된 입력값");
        }
        return new MemberDto(id, "hello " + id);
    }
}

HandlerExceptionResolver


スプリングMVCは、コントローラ外から異常が放出された場合に異常を解決し、動作を再定義する方法を提供する.コントローラから放出される例外を解決し、動作を変更する場合は、HandlerExceptionResolverを使用します.
ExceptionResolverと略称します.

ExceptionHandlerが有効になる前に、WASでDispatcherServiceletを呼び出すと、DispatcherServiceletはpreHandlerを呼び出し、ハンドルでHandlerアダプタを呼び出してControllerを呼び出す.例外が発生すると、発生した例外がDispatcherServiceletに渡され、PostHandleは呼び出されず、aftCompletionを呼び出すとWASに例外が発行される.これは伝え方です.
このときWASは除外され,サーバに異常が発生したと考えられるため,500個のエラーが投げ出される.

ExceptionHandlerを適用した後、WASでDispatcherServiceを呼び出すと、DispatcherServiceはpreHandleを呼び出し、ハンドルでHandlerアダプタとControllerを呼び出し、異常が発生した場合、発生した異常をDispatcherServiceに渡します.
DispatcherServiceletがExceptionResolverを呼び出します.ExceptionHandlerは、発生した例外を解決しようとします.この時点で解決された場合、render(モデル)を呼び出し、通常の応答としてWASに送信できます.
簡単に言えば、ExceptionResolverは例外を解決するソリューションです.
cf)ExceptionHandlerもPostHandlerを呼び出すことはありません.

HandlerExceptionResolver-インタフェース

public interface HandlerExceptionResolver {

	@Nullable
	ModelAndView resolveException(
			HttpServletRequest request, HttpServletResponse response,
            		@Nullable Object handler, Exception ex);

}
ハンドラハンドラ:ハンドラについて
Exception ex:コントローラ上の異常

HandlerExceptionResolver—実装

@Slf4j
public class MyHandlerExceptionResolver implements HandlerExceptionResolver {

    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {

        try {
            if (ex instanceof IllegalArgumentException) {
                log.info("IllegalArgumentException resolver to 400");
                response.sendError(HttpServletResponse.SC_BAD_REQUEST, ex.getMessage());
                return new ModelAndView();
            }
        } catch (IOException e) {
            log.error("resolver ex", e);
            e.printStackTrace();
        }
        return null;
    }
}
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
        resolvers.add(new MyHandlerExceptionResolver());
    }
    
ExceptionHandlerを実装し、IllegalArgumentExceptionが発生したときに応答します.400個のエラーをsendError()に入れます.
return new ModelAndView(); 新しいModelAndViewオブジェクトをNull値に戻すと、通常のストリームで応答し、WASに渡されます.
すなわち、ExceptionHandlerはコントローラからの異常を受信し、この異常を解決して正常な応答を返す.
ExceptionHandlerがModelAndViewに戻る目的は、try、catchのようにExceptionを処理し、通常のストリームに変更することです.その名の通り、Exceptionを解決するのが目的です.
上記のコードは、EllegalArgumentExceptionが発生したときに応答します.sendError(400)を呼び出してHTTPステータスコードを400に指定し、空のModelAndViewを返します.

戻り値の操作方法


DispatcherSevletがHandlerExceptionResolverに従って値を返す方法は次のとおりです.
  • 空のModelAndView:New ModelAndView()のように空のModelAndViewを返すと、サーブレットはビューをレンダリングせずに通常のストリームを返します.
  • 指定
  • ModelAndView:ModelAndViewでビュー、モデルなどの情報の戻り値を指定することで、ビューをレンダリングします.
  • null:nullを返すと、次のExceptionResolverが検索されて実行されます.処理可能なExceptionResolverがない場合、例外処理はできず、既存の例外をサーブレットから放出します.-->WASは通常の応答ではなく異常を受信します.
  • ExceptionResolverの利用

  • 異常状態コード変換
    応答
  • 例外.ステータスコードエラー
  • の処理をサーブレットに依頼するsendError(xxx)呼び出しに変更
  • の後、WASはサーブレットエラーページを検索し、スプリングガイドのデフォルト/error呼び出し
  • のような内部呼び出しを呼び出す.
  • ビューテンプレートの処理
  • ModelAndViewに値を入力することで、例外の新しいエラー画面をレンダリングし、クライアントに
  • を提供します.
  • API応答
  • response.getWriter().print("hello");
  • 上のコードのようにHTTP応答本体に直接データを入れるようにしてもよい.ここでJSON応答でAPI応答処理を行うことができる.