概要
Web開発者にとって、MVCモデルは誰にとっても非常に馴染みがあります。 SpringMVCでは、条件を満たすリクエストは、リクエストの配布に責任があるDispatcherServletに入ります。 DispatcherServletは、リクエストURLをコントローラーにマッピングします(ハンドライングで保存します)。 HandLermappingは、ついに特定の処理オブジェクトハンドラー(つまり、プログラムしたときに書いたもの)を含むHandLerexecutionChainを返します。コントローラー)および一連のインターセプター。現時点では、DispatcherServletは、返されたHandlerexecutionchainのハンドラーのハンドラーに基づいて、このプロセッサタイプをサポートするハンドラアダプターを見つけます。プロセッサアダプターでは、最終的にコントローラーの要求応答方法を呼び出し、結果ビュー(ModelAndView)を返します。結果ビューを取得した後、結果はレンダリング方法を介して表示されます。
ハンドマッピング継承システム:
SpringMVCは、ハンドラープロセッサへの配布を要求します。このステップは、ハンドライングモジュールを介して解決されます。ハンドライングもインターセプターを処理します。
最初にハンドラーマッピングの継承ツリーを見てみましょう
このような分類を大まかに作成できます。
1.インターフェイスHandlermapping、APIを定義します。HandLerexecutionChainGethandler(httpservletrequestリクエスト)スロー例をスローします。
2。基本的な抽象クラス:主にコンテキスト環境を準備し、Gethandlerinternalフックを提供し、インターセプターをHandLerexecutionChainにカプセル化します
3. @Controller、@RequestMappingの使用。注釈に基づいて
4.構成ファイルのURLからハンドラーにsimpleurlhandLermappを構成する
5。beannameurlhandlermappingはデフォルトで実装されています
6。コントローラーサブクラスのマッピング
ハンドラーラッピングを見てみましょう。GethandlerAPIだけが非常に簡単です。
// handlermappingPackage org.springframework.web.servlet; public interface handlermapping {handlerexecutionchain gethandler(httpservletrequest request)スロー例外;}抽象化はそれほど単純ではありません
まず、Abstracthandlermappingと実装されたインターフェイスによって継承されたクラスを見てください
パッケージorg.springframework.web.servlet.handler; public abstract class abstracthandlermappingは、webapplicationobjectsupportimplements handlermappingを拡張します{// ...} WebApplicationObjectSupportは、コンテキストApplicationContextとServletContextを提供するために使用されます。
ここにはinitapplicationContextメソッドもありますが、これは将来的によく使用されます。 Abstracthandlermappingは直接上書きされます。
ApplicationContextAwareおよびServletContextAwareインターフェイスは、親クラスにまだ実装されており、Springの概念は非常に統一されています。
注文されたものは、コレクションソートに使用されます。
引き続き抽象化の特性を見てみましょう
// abstracthandlermapping //注文は最大値を割り当て、優先度は最小のprivate int order = integer.max_value; //デフォルト:非注文と同じ//デフォルトハンドラー、ここで使用されるobejct、およびサブクラスの実装、Handlermethod、HandlerexecutionChainおよびその他のプライベートオブジェクトDefaultherlerを使用; antpathmatcher(); //インターセプター構成:、ハンドラーマッピングプロパティ設定;、エクステンデントインターセプター設定プライベート最終リスト<オブジェクト>インターセプター= new arraylist <object>();マッチが渡されますプライベート最終リスト<mappedInterceptor> mappedInterceptors = new ArrayList <MappedInterceptor>();
インターセプターの初期化を確認してください。
// abstracthandlermapping@overrideRidedotected void initapplicationContext()throws beansecception {endoctinterceptors(this.interceptors); detectectectectectectectectectectectinterceptors(this.mappedInterceptors); initecterceptors();}/***サブクレース拡張インターセプターに提供されます。 {}/***アプリケーションの下のマッピングインターセプターをスキャンして、マッピングインターセプターに追加します*/保護されたvoid detectectmappedInterceptors(list <mappedInterceptor> mappedInterceptors){mappedInterceptors.addall(beanfactututils.beansoftypeincterceptors(getapplicedcontext) false).values());}/***マッピングインターセプターを収集し、ハンドラーインターセプターおよびWebRequestInterceptorに適応します*/保護されたvoid interceptors(){if(!this.interceptors.isempty()){for null){新しいIllegalargumentException(インターセプターアレイの「エントリ番号」 + i + "をスローアレイはnull") HandlerInterceptor AdaptInterceptor(Object Interceptor){if(Interceptor Instance of handlerInterceptor){return(handlerinterceptor)interceptor;} else if(interpector instance of webrequestinterceptor){return new webrecesthandlerinterceptoradapter(return interpector);サポート: " + interceptor.getClass()。getName());}}次に、Gethandler(httpservletrequestリクエスト)の実装があります。ここでも、サブクラス実装のためにGethandlerinternal(httpservletrequestリクエスト)を留保します。
// abstracthandlermapping Public final handlerexecutionchain gethandler(httpservletrequest request)throws {object handler = gethandlerininternal(request); if(handler == null){handler = getDefaulthler();} if(handler = = null; Instanceof string){string handlername =(string)handler; handler = getApplicationContext()。getBean(Handlername);} return gethandlerexecutionchain(handler、request);}保護されたオブジェクトgethandlerinternal(httpservletrequest request)shrows recumpect;最後に、インターセプターをHandLerexecutionChainにカプセル化します
AdaptedInterceptorsを直接追加します
MappedInterceptorsは、URLに従って一致した後に追加する必要があります
// abstracthandlermapppected handlerexecutionchain gethandlerexecutionchain(オブジェクトハンドラー、httpservletrequest request){handlerexecutionchain chain =(handler instance of handlerexecutionchain)ハンドラー:新しいHandlerexecutionchain(Handler); Chain.AddInterceptors(getAdaptedInterceptors()); string lookuppath = urlpathhelper.getlookuppath(request); {Chain.AdddInterceptor(mappedInterceptor.getInterceptor();}} return Chain;}コントローラーサブクラスのマッピング、このブランチは最初にクラス継承を見ています
こちらの各カテゴリの主な責任について話しましょう
1。コンテキスト環境を抽象化します。 Gethandlerinternalフックを提供します。 HandLerexecutionChainにインターセプターをカプセル化します
2。abstracturllhandlermappは、サブクラス使用のためにハンドラーを登録する方法を実装します。 Gethandlerinternalを実装し、サブクラスによって初期化された構成情報に基づいてハンドラーを見つけます。
3。AbstractDetectingurllhandLermappingアプリケーションの下でオブジェクトをスキャンし、反復後、フックメソッドを提供して、それをフィルタリングする方法を決定するためにForurlsforhandlerを決定します。
4。AbstractControllurrurrurlhandLermappingを実装して、Handlerの操作(構成ファイルの構成)を追加し、サブクラスの実装用のフックメソッドbuildurlsforhandlerを留保します。同時に、コントローラーのサブクラスを判断します
5。ControlerBeanNameHandLermappingBean Nameに基づいてURLを生成します
controllerclassnamehandlermappingクラス名に基づいてURLを生成します
AbstracturllhandLermappingから始めましょう。ここでは、コードを大まかに見ています。慎重に分析する必要がある場合は、<SpringMVCソースコード解釈 - ハンドラーマッピング-AbstracturllhandLermappingシリーズリクエスト配布>に移動してください
ハンドラーの登録
保護されたvoidレジスタハンドラー(String [] urlpaths、string beanname)Beansexception、IllegalStateException {}保護されたVoid RegisterHandler(String Urlpath、オブジェクトハンドラー)BeanSexception、IllegalStateException {}ハンドラーの検索
保護されたオブジェクトgethandlerinternal(httpservletrequestリクエスト)例外{} //ハンドラーで保護されたオブジェクトLookuphandler(String urlpath、httpservletrequestリクエスト)を検索します。 handLerexecutionChainProtectedオブジェクトBuildPathExpositingHandler(オブジェクトRawhandler、String BestMatchingPattern、String PathIthinMapping、Map <String、String> UritemplateVariables){}AbstractDetectingurllhandLermapp、これは拡張されていません。詳細に移動してください<SpringMVCソースコード解釈-HandLermapping -AbstractDetectingurllhandLermapping series>
何をするか:
1. initectectlicationcontextを上書きして、Detectecthandlersを呼び出してOBJCTをスキャンします
2.フックメソッドを提供するハンドラーに応じて、フックメソッドを提供します。
3.親クラスのレジスターハンドラーに電話して登録してください
@OverridePublic void initapplicationContext()throws applicationContextException {super.initapplicationcontext(); detecthandlers();}保護されたvoid detecthandlers()throws beansection {// ...}/*** beanname); AbstractControllururlhandLermapp、これは拡張されていません。詳細に移動してください<SpringMVCソースコード解釈 - ハンドラーラッピング-AbstractDetectingurlhandlermapping series>具体的に何をすべきか。
1. sechineurlsforhandlerを上書きしてロジックを追加していくつかのクラスを削除し、構成ファイルで構成された除外クラスと除外パッケージを使用します。
2。コントローラーのサブクラスかどうかを判断します
3.サブクラスのURLを生成するためのBuildUrlsForHandlerを予約します
@OverrideProtected String [] sequineurlsforhandler(string beanname){class beanclass = getApplicationContext()。getType(beanName); if(iseCilibleFormapping(beanname、beanclass)){return buildurlsforhandler(beanname、beanclass); ISELIGIBLEFORPAPPING(String BeanName、class BeanClass){}保護されたブールisControllerType(class BeanClass){}保護された抽象文字列[] BuildUrlsForHandler(String BeanName、class BeanClass); controllerbeannamehandlermapping and controllerclassnamehandlermappingソースコードを直接見るか、<springmvcソースコード解釈 - ハンドラーラッピング-AbstractDetectingurllhandLermappingシリーズ> simpleurlhandLermappingは、構成ファイルでHandlerにURLを直接構成します。これは、登録ハンドラーを使用して構成ドキュメントにハンドラーを登録するか、コードを直接読み取るか、<springMVCソースコード解釈 - ハンドラーマッピング - simpleurlhandlermapping Initialization>
beannameurlhandlermappingは、URLを生成するか、コードを直接確認するか、<springmvcソースコード解釈 - ハンドラーラッピング - アブストラクトデテクティングラッピングの初期化>を移動するために、ハンドラーを決定することを実装します。
@Controllerの使用、@RequestMappingアノテーションに基づいています
最も硬い骨
最初にクラスの相続を見てみましょう
各カテゴリの責任について話しましょう。特定の分析については、次の記事に移動してください
<springmvcソースコード解釈 - ハンドラーランピング-mappinghandlermapping initialization>
<springmvcソースコード解釈 - ハンドラーマッピング-mappinghandlermappingリクエスト配布>
1。abstracthandlermethodmaping初期化プロセスと、要求時にマップする方法を定義します
初期化:
1.1.1アプリケーションの下のオブジェクトをスキャンします
1.1.2 ISHANDLERフック法をサブクラスに予約して、オブジェクトがハンドラーであるかどうかを判断する
1.1.3各ハンドラーを繰り返しスキャンして、要件を満たすメソッドを見つけます。ここでの判断は、getMappingFormethodを実装するためにまだサブクラスに任されています
1.1.4見つかったプロセッサを登録する場合、一致する条件要求のmappinginfoがハンドラーにのみマッピングできるようにする必要があります
1.1.5一致する条件に従ってURLを取得し、同じことはプロセスを定義するためだけです。特定のアルゴリズムはサブクラスに任されて、getMappingPathPatternsを実装します
配布処理を要求します:
1.2.1直接文字列マッチング方法、ハンドラーを検索します
1.2.2マッチング条件検索、ここの特定のアルゴリズムは、getMatchingMappingにサブクラスに引き渡されます
1.2.3ソートして、最高のマッチングハンドラーを取得します。ここの並べ替え方法は、まだサブクラス処理getmappingconparatorです
1.2.4マッチングのカプセル化とマッチングハンドラーのそれぞれ
2。RequestMappingInfohandLermappingは、requestmappinginfoを使用して一致する条件を実装し、requestmappinginfoの初期化がサブクラスに任されています
2.1 url-> getMappingPathPatternsをrequestMappingInfoに従って生成します
2.2マッチング条件を使用してハンドラーを見つけます - > GetMatchingMapping
2.3コンパレータアルゴリズム - > getMappingComparator
2.4ハンドルマッチを上書きし、キャッシュn要求する複数の情報
登録パターン、最適なマッチングパターン、URLの解析パラメーター、URL、MediAtypeで解析された多値パラメーター
2.1.5 Handlernomatchを上書きして、最後の闘争の後にもう一度一致させてみてください
3.リクエストマッピングハンドレマッピングAnnotation @Controller @RequestMappingに従ってRequestMappingInfoを生成し、ISHANDLERを検証します
3.1 AfterPropertiessetを上書きし、ファイルの接尾辞を追加して判断します
3.2 Ishandlerを実装し、クラスの注釈の1つが正しいです。
3.3注釈コンテンツを分析し、RequestMappingInfoインスタンスを作成します