フロントエンドコントローラーは、MVCフレームワーク全体の中で最もコアな部分です。主に、要件を満たす外部リクエストを傍受し、リクエストをさまざまなコントローラーに配布するために使用されます。コントローラーの処理の結果によると、対応する応答を生成し、クライアントに送信します。フロントエンドコントローラーは、フィルター(Struts2がこのメソッドを使用する)またはサーブレット(スプリングMVCフレームワーク)を使用して実装できます。
プリコントローラーとして、DispatcherServletはWebサーバーの入り口であり、Spring MVCの最も重要なクラスです。ライフサイクルを通じて、Webサーバーの理解を深めることができます。
サーブレットのライフサイクル
まず、サーブレットのライフサイクルを思い出しましょう。
サーブレットのライフサイクルは、3つの段階に分かれています。[サーブレットのライフサイクルの詳細な説明と作業原則]
1。init()メソッドは、初期化フェーズでinit()と呼ばれます。サーブレットがロードされた後、サーブレットコンテナはサーブレットインスタンスを作成し、初期化のためにサーブレットのinit()メソッドを呼び出します。 init()メソッドは、サーブレットの生涯にわたって1回のみ呼び出されます。
2。クライアント要求段階に応じてサービス()メソッドを呼び出す
3。終了段階でDestroy()メソッドを呼び出します
サーブレット初期化フェーズ
次の瞬間に、サーブレット容器はサーブレットをロードします。
1.サーブレット容器が起動すると、一部のサーブレットが自動的にロードされます。それを実装するには、web.xmlファイルに<servlet> </servlet>の間に次のコードを追加する必要があります。
<Loadon-StartUp> 1 </roadon-startup>
2。サーブレット容器が開始された後、クライアントは初めてサーブレットにリクエストを送信します
3。サーブレットクラスファイルが更新されたら、サーブレットをリロードします
DispatcherServletの構造
上記の知識を確認した後、DispatcherServletの構造を見てみましょう。
DispatcherServletは抽象クラスから継承します:Frameworkservletは間接的にhttpservletを継承します(frameworkservletはhttpservletbeanから継承し、httpservletbeanはhttpservletから継承します)
サーブレットの初期化
Protected void initstrategies(applicationContext Context){initMultiPartresolver(Context); //アップロードして解析します。リクエストタイプがMultiPARTの場合は、ファイルアップロードしてMultiPartresolverを介して解析します。 initlocaleresolver(コンテキスト); // initthemeresolver(コンテキスト)のローカリゼーション解析; //テーマ解析Inithandlermappings(コンテキスト); //プロセッサInithandleradaptersへのマッピングリクエスト(コンテキスト); //複数の種類のプロセッサのマッピングInithandLerexceptionSolvers(コンテキスト); // HandlerAdapterを介して複数の種類のプロセッサをサポートします。 //実行中に例外が発生した場合、initRequestToviewNameTranslator(コンテキスト)を解析するためにHandLerexceptionResolverに引き渡されます。 //リクエストを表示名に直接解析しますinitviewResolvers(コンテキスト); // ViewResolverを介して論理ビュー名を特定のビューに解決して、initflashmapManager(コンテキスト)を実装します。 //フラッシュマップマネージャー}リクエストの処理方法:
サーブレットのサービス方法は、HTTP要求を処理します。
Frameworkservlet.javaは、以下に示すように、サーブレットのサービスと破壊方法を定義します。
/** *パッチ要求を傍受するために、親クラスの実装をオーバーライドします *リクエスト。 */ @Override Protected void Service(httpservletrequest request、httpservletResponse応答)servletexception、ioexception {string method = request.getmethod(); if(method.equalsignorecase(requestmethod.patch.name())){processRequest(request、response); } else {super.service(request、response); }}次のように定義される7種類のHTTPリクエストタイプ(プラスオプション)があることを知っています。
public enum requestmethod {get、head、post、put、pat、patch、delete、options、trace} Frameworkservletのサービス()は、さまざまなリクエストを処理します。一般的な投稿を使用して説明します。
/***このリクエストを処理し、結果に関係なくイベントを公開します。 * <p>実際のイベント処理は、要約 * {@link #doservice}テンプレートメソッドによって実行されます。 */保護された最終void ProcessRequest(httpservletrequest request、httpservletResponse応答)servletexception、ioexception {long starttime = system.currenttimemillis();スロー可能なfailurecause = null; localecontext forterlocalecontext = localecontextholder.getLocaleContext(); localecontext localecontext = buildlocalecontext(request); requestAttributes forterattributes = requestContextholder.getRequestattributes(); servletRequestattributes requestattributes = buildRequestattributes(request、response、fortiorattributes); webasyncmanager asyncmanager = webasyncutils.getasyncmanager(request); asyncmanager.registerCallableInterceptor(frameworkservlet.class.getName()、new requestbindingInterceptor()); initcontextholders(request、localecontext、requestattributes); try {doservice(request、response); } catch(servletexception ex){failurecause = ex; Exを投げる; } catch(ioException ex){failurecause = ex; Exを投げる; } catch(throwable ex){failurecause = ex;新しいNestedServleTexception( "要求処理が失敗した"、ex)を投げます。 }最後に{resetcontextholders(request、fortionlocalecontext、forterattributes); if(requestattributes!= null){requestattributes.requestCompleted(); } if(logger.isdebugenabled()){if(failurecause!= null){this.logger.debug( "要求を完了できなかった"、failurecause); } else {if(asyncmanager.isconcurrenthandlingStarted()){logger.debug( "コンカレント処理のために応答を開く"); } else {this.logger.debug( "正常に完了したリクエスト"); }}} publishRequestHandleDevent(request、starttime、failurecause); }} Frameworkservletは、処理フローを抽象的に定義し、サブクラスに任せてメソッドを実装し、特定の要求処理を完了します。
/** *サブクラスは、この方法を実装してリクエスト処理作業を行う必要があります。 * <p>契約は、一般的にオーバーライドされた * {@code doget}または{@code dopost} httpservletメソッドと本質的に同じです。 * <p>このクラスは、例外処理と *イベントの公開が行われることを確認するために呼び出しを傍受します。 * @paramリクエスト現在のHTTPリクエスト * @param応答現在のHTTP応答 * @Throws例外任意の処理障害の場合 * @See javax.servlet.http.httpservlet * @see javax.servlet.servlet.http.httpservlet#dopost httpservletResponse応答)例外をスローします。特定の実装は次のとおりです。
/** *実際のディスパッチのために、DispatcherServlet固有の要求属性と{@link #dodispatch} *に代表者を公開します。 */ @Override Protected void doservice(httpservletrequest request、httpservletresponse応答)スロー例外{if(logger.isdebugenabled()){string resumed = webasyncutils.getasyncmanager(request).hasconcurrentult()? 「再開」: ""; logger.debug( "name '" + getServletname() + "'" +再開 + "処理" + request.getMethod() + "request for [" + getRequesturi(request) + "]"); } // includeを含める場合は、リクエスト属性のスナップショットを保持します。 map <string、object> astributessnapshot = null; if(webutils.isincluderequest(request)){astributessnapshot = new hashmap <string、object>(); enumeration <?> attrnames = request.getAttributEnames(); while(attrnames.hasmoreElements()){string attrname =(string)attrnames.nextelement(); if(this.cleanupafterinclude || attrname.startswith( "org.springframework.web.servlet")){astributessnapshot.put(attrname、request.getattribute(attrname)); }}}} //ハンドラーとオブジェクトの表示でフレームワークオブジェクトを使用できるようにします。 request.setattribute(web_application_context_attribute、getWebApplicationContext()); request.setattribute(locale_resolver_attribute、this.localeresolver); request.setattribute(theme_resolver_attribute、this.themeresolver); request.setattribute(theme_source_attribute、getThemesource()); 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 {dodispatch(request、response); }最後に{if(webasyncutils.getasyncmanager(request).isconcurrentlingstarted()){return; } //インクルードの場合、元の属性スナップショットを復元します。 if(astributessnapshot!= null){restoreattributesafterinclude(request、astributessnapshot); }}}リクエストディストリビューターの実装としてのハイライト:
関数:1。リクエストをハンドラーに配布します(構成の順序でサーブレットマッピング関係を取得)。 2。サーブレットによってインストールされたハンドラーダプターに基づいて処理できる最初のハンドラーをクエリします。 3.ハンドラーはリクエストの処理をトリガーします
/***実際のディスパッチをハンドラーに処理します。 * <p>ハンドラーは、サーブレットのハンドルマッピングを順番に適用することにより取得されます。 *ハンドラダプターは、サーブレットの取り付けられたハンドラダプターをクエリすることで取得され、ハンドラークラスをサポートする最初のものを見つけることができます。 * <p>すべてのHTTPメソッドは、この方法で処理されます。どの方法が受け入れられるかを決定するのは、ハンドラダプターまたはハンドラー *自己次第です。 * @Paramリクエスト現在のHTTPリクエスト * @PARAM応答現在のHTTP応答 * @Throws任意の処理障害の場合 */保護されたvoid dodispatch(httpservletrequest request、httpservletrequess Response)をスローする例外{httpservletrequest processedrequest = request; HandLerexecutionChain MappedHandler = null; boolean multipartrequestparsed = false; webasyncmanager asyncmanager = webasyncutils.getasyncmanager(request); try {modelandview mv = null;例外DispatchException = null; try {processedRequest = checkmultipart(request); MultiPartRequestParsed =(processedRequest!= request); //現在のリクエストのハンドラーを決定します。 mappedhandler = gethandler(processedRequest); if(mappedhandler == null || mappedhandler.gethandler()== null){nohandlerfound(processedRequest、response);戻る; } //現在のリクエストのハンドラーアダプターを決定します。 HandlerAdapter ha = gethandleradapter(mappedhandler.gethandler()); //ハンドラーによってサポートされている場合、ラスト修飾ヘッダーを処理します。 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( "[" + getRequesturi(request) + "]のlast修正値は:" + lastModified); } if(new servletwebrequest(request、response).checknotModified(lastModified)&& isget){return; }} if(new servletwebrequest(request、response).checknotModified(lastModified)&& isget){return; }} if(!mappedhandler.applyprehandle(processedRequest、response)){return; } try {//実際にハンドラーを呼び出します。 MV = ha.handle(processedRequest、response、mappedhandler.gethandler()); }最後に{if(asyncmanager.isconcurrenthandlingStarted()){return; }} applydefaultViewName(request、MV); mappedhandler.applyposthandle(processedRequest、response、MV); } catch(Exception ex){dispatchexception = ex; } processDisPatchResult(ProcessEdRequest、Response、MappedHandler、MV、DispatchException); } catch(Exception ex){triggeraftercompletion(processedRequest、response、mappedler、ex); } catch(erry err){triggeraftercompletionwitherror(processedRequest、response、mappedhandler、err); }最後に{if(asyncmanager.isconcurrenthandlingStarted()){// posthandleおよびaftercompletionの代わりにmappedhandler.applyafterconcurrenthandlingStarted(processedRequest、response);戻る; } //マルチパートリクエストで使用されるリソースをクリーンアップします。 if(multipartrequestparsed){cleanupmultipart(processedRequest); }}}サーブレット破壊
/***このサーブレットのWebApplicationContextを閉じます。 * @see org.springframework.context.configurableapplicationcontext#close() */ @override public void destroy(){getservletcontext()。log( "spring frameworkservlet '" + getServletname() + "'"); // webApplicationContextでclose()のみを呼び出してください。 }}まとめ:
この章の制限により、この記事では要求処理プロセスを導入するだけで、コードの詳細な分析を実施していません。次の記事は、詳細から始まり、Springのコードの美しさを分析します。
上記はこの記事のすべての内容です。みんなの学習に役立つことを願っています。誰もがwulin.comをもっとサポートすることを願っています。