BestMeのブログ -4ページ目

BestMeのブログ

ブログの説明を入力します。

DispatcherServletの本体編
●ソース
protected
void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {

     ...

  //これから必要な部品をrequestに入れる

  //web.xmlで設定したカスタマイズ用プロパティをrequestに入れる

  request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());

  //国際化用のresolverを設定(SessionLocaleResolverCookieLocaleResolverなど)

  //localeResolverinitLocaleResolverで設定され、SpringBeanコンテナから「localResolver」名前で検索し、

  //見つけなかったら、defaultStrategyで設定する

  //DefaultStrategyorg.springframework.web.servlet.DispatcherServlet.propertiesから取り込む

  request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);

  //localeResolverに似てて、テームをアレンジできるように(SessionThemeResolverCookieThemeResolverなど)

  //テームは簡単に言うと、夏の時に、こうする、冬の時に、そうするをできるように

  request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);

  request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());

   //FlashMapは二重送信回避用PRG構造に役たつ、ようするに、Mapにデータを登録しておくと一回のHTTPリダイレクトの最中のみデータが保持され、次回以降のリクエスト時までに自動的に削除されること

   //ソースを読む限り、この中間データはセッションまたはほかの永続化場所に保存することができる、AbstractFlashMapManagerを継承すればOK

       //一般的に、SessionFlashMapManagerをそのまま利用するでしょうか、ようするに、「SessionFlashMapManager.FLASH_MAPS」をキーにしてSessionに保存する

       //実際の処理として①セッションからすべてのFlashMapを取得する②有効期限切れのFlashMapを削除③request pathquery parametercurrent requestにマッチするFlashMapを取得

       //falshMapの有効期限はAbstractFlashMapManagerの中で、flashMapTimeout = 180秒デフォルトとして定義しています。

  FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);

  if (inputFlashMap != null) {

    request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));

  }

  request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());

  request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);

  try {

            //実際のHandler処理はここから

    doDispatch(request, response);

  finally {

    if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {

      return;

    }

    // Restore the original attribute snapshot, in case of an include.

    if (attributesSnapshot != null) {

      restoreAttributesAfterInclude(request, attributesSnapshot);

    }

  }

 }

}

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {

  HttpServletRequest processedRequest = request;

  HandlerExecutionChain mappedHandler = null;

  boolean multipartRequestParsed = false;

     //非同期を管理するやつを取得しておく

  WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

  try {

    ModelAndView mv = null;

    Exception dispatchException = null;

    try {

              //spring容器の中で、multipartResolver有無をチェックして、ある場合、multipartResolverisMultipartreqeustをチェックする

              //multipartの場合、HttpServletRequestrequestMultipartHttpServletRequestに変換する

              processedRequest = checkMultipart(request);

              //オブジェクト間の!=のチェックは普段あまり使わないんですが、ここのメリットはcheckMultipart戻り値は変換後のオブジェクトだけOKのことですね。

              multipartRequestParsed = (processedRequest != request);

      //事前に生成したthis.handlerMappingsからrequest情報にマッチするHandlerを取得

              mappedHandler = getHandler(processedRequest);

      if (mappedHandler == null || mappedHandler.getHandler() == null) {

        noHandlerFound(processedRequest, response);

        return;

      }

      //リクエストハンドラーを特定のインターフェースに適合させる

              HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

      // Process last-modified header, if supported by the handler.

              //ここはLash-Modifiedのキャッシュアルゴリズムについて話します

              //URLでリクエスト、200を返しながら、リクエスト対象ファイルがサーバー上の最後の更新日時を表すLast-Modifiedを追加 例:“Last-Modified:Wed, 14 Mar 2012 10:22:42 GMT”

              //②二回目同じURLでリクエスト場合、ヘッダーにif-Modified-Sinceで該当資源が更新されたかどうかを質問しておく 例:“If-Modified-Since: Wed, 14 Mar 2012 10:22:42 GMT”

              //変化がなければ、HTTP 304を返す

              //springの中で、Last-Modifiedを使いたい場合、該当ControllerLastModifiedを実装すればできる、(getLastModifiedのみ)

      String method = request.getMethod();

      boolean isGet = "GET".equals(method);

      if (isGet || "HEAD".equals(method)) {

        long lastModified = ha.getLastModified(request, mappedHandler.getHandler());

        if (logger.isDebugEnabled()) {

          logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);

        }

      if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {

        return;

      }
    }

            //HandlerInterceptor処理のため

            //preHandle() Handlerの実行前

            //postHandle() Handlerの実行後

            //afterCompletion() すべてのリクエスト処理完了後(viewの生成の後)

    if (!mappedHandler.applyPreHandle(processedRequest, response)) {

      return;

    }

    try {

                //実際のリクエストを処置して、viewを貰う

      mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

    finally {

      if (asyncManager.isConcurrentHandlingStarted()) {

        return;

      }

    }

    applyDefaultViewName(request, mv);

            //HandlerInterceptor処理のため

    mappedHandler.applyPostHandle(processedRequest, response, mv);

  catch (Exception ex) {

    dispatchException = ex;

  }

      //処理結果がModelAndViewまたはExceptionによって、結果を生成する

  processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);

catch (Exception ex) {

  triggerAfterCompletion(processedRequest, response, mappedHandler, ex);

catch (Error err) {

  triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);

finally {

  if (asyncManager.isConcurrentHandlingStarted()) {

    // Instead of postHandle and afterCompletion

    mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);

    return;

  }

  // Clean up any resources used by a multipart request.

  if (multipartRequestParsed) {

    cleanupMultipart(processedRequest);

}}}