Spring MVCは、Springシリーズのフレームワークで最も頻繁に使用される部分です。Spring Bootであろうと従来のSpringプロジェクトであろうと、Webプロジェクトである限り、SpringMVCパーツが使用されます。したがって、プログラマーはMVCの部分に習熟している必要があります。このブログは、SpringMVCがリクエストを処理するプロセスを簡単に分析します
クライアントからサーバーに送信されて処理される要求のプロセス全体は、実際には非常に複雑です。このブログでは、主に、リクエストがサーバーに到着し、コアコンポーネントであるDispatcherServletによって処理されるときの終了プロセス(Filterの処理プロセスは含まない)を紹介しています。
1.処理フロー分析
サーブレットはリクエストの処理時にservice()メソッドを呼び出すため、DispatcherServletがリクエストを処理する方法もservice()メソッドからです(デバッグの場合は、DispatcherServletのサービスメソッドからデバッグを開始することをお勧めします) 。FrameworkServletはHttpServletのサービスメソッドを書き換えます。このサービスメソッドはFrameworkServletのprocessRequest()メソッドを呼び出し、processRequest()はDispatcherServletのdoService()メソッドを呼び出し、最後にDispatcherServletのdoDispatcher()メソッドを呼び出します。統合処理リクエストのメソッド呼び出しプロセスは上記のとおりです。以下のコードを見てみましょう。
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
if (HttpMethod.PATCH == httpMethod || httpMethod == null) {
processRequest(request, response);
}
else {
//这边调用了HttpServlet的service()方法,但由于FrameWorkServle重写了doGet、doPost等方法,所以最终还是会调用到processRequest方法
super.service(request, response);
}
}
FrameworkServletのprocessRequest()メソッドを見てください。
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
long startTime = System.currentTimeMillis();
Throwable failureCause = null;
LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
LocaleContext localeContext = buildLocaleContext(request);
RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());
initContextHolders(request, localeContext, requestAttributes);
try {
//这边调用DispatcherServlet的doService()方法
doService(request, response);
}
catch (ServletException ex) {
failureCause = ex;
throw ex;
}
catch (IOException ex) {
failureCause = ex;
throw ex;
}
catch (Throwable ex) {
failureCause = ex;
throw new NestedServletException("Request processing failed", ex);
}
finally {
resetContextHolders(request, previousLocaleContext, previousAttributes);
if (requestAttributes != null) {
requestAttributes.requestCompleted();
}
if (logger.isDebugEnabled()) {
if (failureCause != null) {
this.logger.debug("Could not complete request", failureCause);
}
else {
if (asyncManager.isConcurrentHandlingStarted()) {
logger.debug("Leaving response open for concurrent processing");
}
else {
this.logger.debug("Successfully completed request");
}
}
}
publishRequestHandledEvent(request, response, startTime, failureCause);
}
}
doService()メソッドの具体的な内容については後で説明します。これがdoDispatcher()の内容です。
まず、要求されたパスに従ってHandlerMethod(Controllerのメソッドに対応するMethod Reflection属性を使用)を見つけ、次にパスに対応するインターセプターを照合し、HandlerMethodとインターセプターを使用してHandlerExecutionChainオブジェクトを作成します。HandlerExecutionChainオブジェクトは、HandlerMappingインターフェイスによって提供されるメソッドを介して取得されます。HandlerExecutionChainを取得した後、ModelAndViewオブジェクトはHandlerAdapterオブジェクトを介して処理のために取得されます。HandlerMethod内部ハンドルの場合、さまざまなHandlerMethodArgumentResolver実装クラスを使用してHandlerMethodパラメーターを処理し、さまざまなHandlerMethodReturnValueHandler実装クラスを使用して戻り値を処理します。最終的な戻り値はModelAndViewオブジェクトに処理され、この期間中に発生した例外はHandlerExceptionResolverインターフェイス実装クラスによって処理されます。
SpringMVCがリクエストを処理するプロセスを要約します。
- まず、アプリケーションコンテキストオブジェクトWebApplicationContextを検索し、それを属性としてリクエストにバインドして、コントローラーや他のコンポーネントが使用できるようにします。
- ロケールリゾルバーをリクエストにバインドして、他のコンポーネントがリクエストの処理(ビューのレンダリング、データの準備など)時にリージョンに関する情報を取得できるようにします。アプリケーションがエリア関連の情報を解決する必要がない場合。
- **テーマパーサーをリクエストにバインドして、他のコンポーネント(ビューなど)がレンダリングするテーマファイルを認識できるようにします。同様に、テーマ関連の機能を使用する必要がない場合は、無視してください。マルチパートファイルプロセッサを構成すると、フレームワークはファイルがマルチパート(複数のパートに分割され、継続的にアップロードされる)であるかどうかを確認します。その場合は、リクエストをMultipartHttpServletRequestオブジェクトにラップして、処理チェーン内の他のコンポーネントがさらに処理できるようにします。マルチパートファイル転送処理に対するSpringのサポートについて。
- リクエストに適したハンドラーを見つけます。対応するプロセッサが見つかった場合、プロセッサに関連付けられた実行チェーン全体(プリプロセッサ、ポストプロセッサ、コントローラなど)が実行され、対応するモデルの準備またはビューのレンダリングが完了します。プロセッサの場合モデルの場合、フレームワークは対応するビューをレンダリングします。モデルが返されない場合(おそらく、フロントプロセッサとバックプロセッサがセキュリティの問題などの理由でリクエストをインターセプトしたため)、フレームワークはビューをレンダリングしません。現時点では、リクエストの処理は処理チェーンによって完了(このプロセスはdoService()およびdoDispatcher()が行うことです)
1。最初に、ユーザーは要求を送信します-> DispatcherServlet。要求を受信した後、フロントコントローラーはそれ自体を処理しませんが、委任します処理のために他のリゾルバに送信します。統合アクセスポイントとして、グローバルプロセス制御を実行します。
2. DispatcherServlet-> HandlerMapping、HandlerMappingは、リクエストをHandlerExecutionChainオブジェクト(ハンドラープロセッサ(ページコントローラー)オブジェクト、複数のHandlerInterceptorインターセプターを含む)オブジェクトにマップします。このストラテジーモードを使用すると、新しいマッピングストラテジーを簡単に追加できます。
3. DispatcherServlet-> HandlerAdapter、HandlerAdapterは、複数のタイプのプロセッサー、つまりアダプター設計パターンのアプリケーションをサポートするために、プロセッサーをアダプターとしてパッケージ化するため、多くのタイプのプロセッサーを簡単にサポートできます。
4. HandlerAdapter->プロセッサ関数処理メソッドを呼び出すと、HandlerAdapterは適応結果に従って実際のプロセッサ関数処理メソッドを呼び出して関数処理を完了し、ModelAndViewオブジェクト(モデルデータ、論理ビュー名を含む)を返します。
5. ModelAndView-> ViewResolverの論理ビュー名。ViewResolverは論理ビュー名を特定のビューに解決します。この戦略モードを使用すると、他のビューテクノロジーを簡単に変更できます。
6.ビュー->レンダリング、ビューは受信モデルモデルデータに従ってレンダリングします。ここでのモデルは実際にはマップデータ構造であるため、他のビューテクノロジーを簡単にサポートできます。
7.制御権がDispatcherServletに返され、DispatcherServletがユーザーに応答を返し、このプロセスが終了します。
2.フローチャートをリクエストします
それでも、この図はより明確です。このプロセスは、コードに基づいて明確に説明できないことがわかりました。また、プロセス全体が非常に長く、コードが多いため、コードを投稿しません。これは、この図に基づいたプロセス全体のコンポーネントの機能の要約です。
-
DispatcherServlet:コアコントローラー、すべてのリクエストは最初にDispatcherServletに入り、統合配布されますが、外観モデルのように感じますか?
-
HandlerMapping:このコンポーネントの役割は、ユーザーが要求したURLをHandlerExecutionChainにマップすることです。このHandlerExecutionChainは、HandlerMethodとHandlerInterceptorを組み合わせたものです。Springは、起動時にデフォルトで多くのHandlerMappingコンポーネントを挿入します。最も一般的に使用されるコンポーネントは、RequestMappingHandlerMappingです。
上記のHandlerMethodコンポーネントとHandlerInterceptorコンポーネントは、それぞれコントローラーのメソッドとインターセプターに対応しています。インターセプターは、HandlerMethodメソッドが実行される前に実行されます
** HandlerAdapterコンポーネント、このコンポーネントの主な機能は、HandlerMethodのパラメーターの変換、メソッドの実行、戻り値の変換などです。HandlerMethodArgumentResolver、** HandlerMethodReturnValueHandler、RequestResponseBodyMethodProcessor、HttpMessageConvertなどのコンポーネントを含む多くの詳細が関係しています。
- HandlerAdapterコンポーネントを実行すると、ビューモデルを表すModleAndViewコンポーネントが取得されます。
ModleAndViewを取得した後、インターセプターのpostHandleメソッドが実行されます。
上記の実行中に例外が発生した場合、それはHandlerExceptionResolverによって処理されます。
最後に、モデルパーサーは上記のModleAndViewを解析し、ビューを取得してクライアントに返します。インターセプターのafterCompletionメソッドも、クライアントに戻る前に実行されます。
上記は、リクエストを処理するSpring MVCの詳細な内容です。SpringMVC処理リクエストの詳細については、エディターに従うか、詳細についてwx1411943564注釈(csdn)を追加してください。