ディレクトリ
実行フローSpringMVCのソースを理解する観点から、
SpringMVCの実装プロセス多くのオンラインの記事がありますが、説明チャートやテキストの説明が非常に詳述されて流れるように持っているが、あなたが特定のプロセスを介してソースコードを所有していない場合は、単に丸暗記、実際には、再度行きます。私はポストを開き、SpringMVC、より深い印象のソースコードの実行フローの観点から、再びそれをくししたいと思います。
はじめにSpringMVC
SpringMVCを使用フロントエンドコントローラ(コントローラフロント)要求を処理するために+各サービスプロセッサ(コントローラ)。最終的にはフロント、特定のスケジューリングルールを通過するトラフィックの検索、特定のプロセッサの処理を担当コントローラ、および代表者へのすべての要求に応えて、特定のビジネスロジックを実行するためのサービスプロセッサへの要求、プロセッサに戻り、モデル、コントローラ、フロントエンドサービスモデルデータに、そしてビュービューをレンダリングするためのフロントコントローラモデル。
アイデアの源解析
悪循環に陥る傾向があり、学生のソースコードを見て、ポイントはあまり詳細に身を、より多くのかすかな手放すことになるまで、初めは、層ごとを理解するために見ることができるかもしれないが、これらの詳細は、実際には主な流れですその後で彩られ、大きな影響を持っていませんでした。見終わった後、別の詳細に自分自身をさせる、ゼロから再スタートしなければなりませんでした。ただ、コードの実行の一般的な流れを理解し、一般的なフレームワークやアイデアを参照するには、ソースコードの必要性を見始めたときに実際には、自分が細部の泥沼に陥ることはできません。この記事では、我々はSpringMVCの実行の流れを理解することも重要なインタフェースを理解し、そして場合は、実装プロセスSpringMVCを整理するためのエントリポイントとして、いくつかの主要なインターフェイスですので。ちょうどインターフェイス機能を理解するために、これがあるので、ない具体的な懸念は、ロジックを実装します。我々は、一般的なプロセスを理解すると、それだけですべての特定のカテゴリを分割。著者後に自分自身を理解するための具体的な例と組み合わせて、独自の定義による要求を処理するために、これらのインタフェースを実装します。
読むSpringMVCソースは2がある私の最大の感じを与えました:
- オープンクローズ原則、高度にスケーラブルでSpringMVCは、我々は唯一、インターフェイスがコンテナに追加された特定のインターフェイスを実装する必要があり、私たちは私たちの拡張機能を実現することができ、あなたは拡張のためのオープン、任意のコードを変更する必要はありません。そして、キーの方法が変更のため閉鎖されている修正finalクラス、で達成されました。
- 指向プログラミング・インタフェース、すべての重要なプロセスコード、ほとんどすべてのインタフェースの呼び出しではなく、上記の特定のクラスに固有。
ソースを読みます
注:源码版本为 spring-webmvc-5.2.2.RELEASE.jar
いくつかの重要なインタフェースおよびクラス
ハンドラーマッピング
public interface HandlerMapping {
@Nullable
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}
プロセッサの特定の要求にマップされた関係をHandlerMapping、メモリは、Aメモリデータマップ<要求ハンドラ>として理解することができ、HandlerMappingハンドラをマップからの要求に応じて返され見つかりました。HandlerExecutionChainだけハンドラとそれに対応するインターセプタインターセプタは、パケット化。
スケジューリング・ルールは、以前に処理取得要求HttpServletRequestの特定のクラス、HandlerExecutionChainリターンをパッケージに要求処理を要求することによって、述べ。オブジェクトハンドラプロセスは、特定のリクエストクラスであることを特徴HandlerExecutionChain。
public class HandlerExecutionChain {
private final Object handler;
@Nullable
private HandlerInterceptor[] interceptors;
@Nullable
private List<HandlerInterceptor> interceptorList;
}
私たちは今、その後、どのように我々はそれを行うために、特定の方法の実装を通過するように対処するか、リクエストによってクラスを処理して、特定のを見つけますか?その後、我々はHandlerAdapterを必要とします。
ハンドラアダプタ
public interface HandlerAdapter {
/**
* 通过方法 supports 判断适配器是否适配这种类型的Handler,返回true则代表适配。
*/
boolean supports(Object handler);
/**
* 如果适配则通过方法 handle 去让 Object handler 执行具体的处理方法。
*/
@Nullable
ModelAndView handle(HttpServletRequest request, HttpServletResponse response
, Object handler) throws Exception;
long getLastModified(HttpServletRequest request, Object handler);
}
ビジネスで具体的な処理プロセッサハンドラを実行するための助けフロントエンドコントローラにHandlerAdapterプロセッサアダプタなので、フロントエンド制御機は、フロントコントロールマシン上HandlerAdapterは、プロセッサの詳細を遮断することを、具体的な実装の詳細に焦点を当てる必要はありません。
ModelAndView
public class ModelAndView {
/** View instance or view name String. */
@Nullable
private Object view;
/** Model Map. */
@Nullable
private ModelMap model;
データモデルとビュー名の論理ビューをパッケージ化します。
オブジェクト・ビューは、一般的に、String型の論理ビュー名です。
地図のための基本となるタイプの役割でMVCモデルのModelMap。
ViewResolver
public interface ViewResolver {
@Nullable
View resolveViewName(String viewName, Locale locale) throws Exception;
}
特定のビューの名前たviewNameビューを見つけるためのロジックを解析し、表示はガイダンスを見つけるために、コントローラの先端のビューを詳しく説明しました。
見る
public interface View {
void render(@Nullable Map<String, ?> model, HttpServletRequest request
, HttpServletResponse response) throws Exception;
}
データモデルを通じてビューをレンダリングするrenderメソッドを呼び出します。
リクエストパラメータ地図は<文字列は、?>モデルモデルは、SpringMVCでの役割を果たしています。
たとえば、私たちは、この方法は、JSON形式の出力にロジックをモデル化することであるレンダリング、JSONデータ形式を返すようにしたいです。
それとも我々は、我々はディスプレイのJSPページ上の特定のモデルに解決することができ、JSP返すようにしたいです。
フロントコントローラのDispatcherServlet
SpringMVCでは、フロントエンドコントローラとしてのDispatcherServlet、制御プロセスとサービスの特定の実装では、コードの主実行フローは、このクラスでもあります。
ここでコードを実行するためのキーを保持し、読者がコードの特定の行を見つけるために、特定のキーワードを検索することができ、簡素化のDispatcherServletソースは、唯一の重要な実装プロセスを含んでいます。
public class DispatcherServlet extends FrameworkServlet {
protected void doDispatch(HttpServletRequest request,
HttpServletResponse response) throws Exception {
HandlerExecutionChain mappedHandler = null;
ModelAndView mv = null;
mappedHandler = getHandler(processedRequest);
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
render(mv, request, response);
}
protected void render(ModelAndView mv, HttpServletRequest request
, HttpServletResponse response) throws Exception {
String viewName = mv.getViewName();
view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
view.render(mv.getModelInternal(), request, response);
}
コードの流れ:
- 取得プロセッサ:特定のハンドラを見つけるためHttpServletRequestのリクエストによってHandlerMapping
- 取得プロセッサ対応アダプター:ハンドラが特定のHandlerAdapterを見つけます
- 処理論理プロセッサを呼び出す:HandlerAdapterハンドラが実行する具体的な呼処理ロジック戻りのModelAndView
- 分析ビュー:ViewResolverはのModelAndView論理ビュー名によって特定のビューを見つけます。
- ビューをレンダリング:レンダリングするためのデータモデルを表示します。
取得プロセッサ
@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
for (HandlerMapping mapping : this.handlerMappings) {
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
起動時のSpringMVCは、インターフェイスを実装してコンテナにこれらのクラスを追加し、すべてのHandlerMappingクラスをスキャンします。
取得プロセッサ・サイクルは、実際に私たちは停止し、リターンを見つけ、HandlerMappingクラス、コールgetHandler()メソッドを実現しています。
各タイプには、独自に対応するハンドラHandlerMappingを持っています。例えばHandlerMapping RequestMappingHandlerMappingに対するデフォルトのプロセッサSpirngMVCコントローラ。
アダプタ・プロセッサを入手
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
for (HandlerAdapter adapter : this.handlerAdapters) {
if (adapter.supports(handler)) {
return adapter;
}
}
}
}
支持体法がtrueを返す限り、これは適応ハンドラを表すようにし、ロジックとして取得プロセッサは、決意ロジックは、先に記載されています。
同じことが、ハンドラは、対応するHandlerAdapterを持つべきでもあります。コントローラRequestMappingHandlerAdapterに対応します。
だから我々は、独自のプロセッサの定義を書きたい場合。我々は、我々自身のHandlerクラスとHandlerMappingとHandlerAdapterに関してを必要とするようにします。
分析ビュー
@Nullable
protected View resolveViewName(String viewName, @Nullable Map<String, Object> model,
Locale locale, HttpServletRequest request) throws Exception {
if (this.viewResolvers != null) {
for (ViewResolver viewResolver : this.viewResolvers) {
View view = viewResolver.resolveViewName(viewName, locale);
if (view != null) {
return view;
}
}
}
return null;
}
これは、すべてのコードを開発へのインタフェースを向いている、まだ同じロジックです。
SpringMVCは、JSP、JSON、FreeMarkerの、thymeleafとして、ビューのレンダリングの様々なサポート。ViewResolverビューは、ビューを表示するには、特定の方法を見つけるためにSpringMVCの必要性を伝えるものを、これらのウィザードということです。
各ビューは、ビューFreeMarkerViewResolver対応リゾルバFreeMarkerViewなどのレゾルバ独自の対応するビューのビューを持っています。
ビューのレンダリング
実際には、それがコードです。
view.render(mv.getModelInternal(), request, response);
単語のビューのレンダリング背が高い上だけ見始めて、感じの良いです。実際には、データモデルは、モデルを表示する方法の種類に基づくべきであるようにすることです。
あなたは、モデルがJSON形式を返すようにしたい場合は、JSON形式にモデルへのビューインタフェースを実現するために移動して、出力ストリームに書き込まれたクラスを応答することができます。
ServletOutputStream out = response.getOutputStream();
baos.writeTo(json);
out.flush();
エピローグ
この記事は、いくつかの重要なSpringMVCインターフェイス、ない特定の分析ロジックの実装クラスによって実行されるプロセスを説明しています。また、自分の感情や経験のソースコードを、独自の外観を共有したいと思いました。、メインの実行の流れを見て、自分が行くためにビジネスロジックのあまりに深いソースを見に落ちるように、スタックの下で実行、デバッグプレビュー方法、検索するための方法によるスタックへの方法として重要なインタフェースを、聞かせてはいけません。そこ領域が誤っているか、別の理解を持っている場合は、私に知らせてください。