1. 程式人生 > >SpringMVC架構及原始碼分析

SpringMVC架構及原始碼分析

SpringMVC

本文在基於SpringMVC 4.3.2.RELEASE版本基礎上,對原始碼進行分析,並探討SpringMVC的原理及用法。
springMVC

整體架構

在瞭解Spring整體架構時,這裡盜用開濤部落格的一張圖。
SpringMVC架構
對該架構流程進行簡單的分析如下:
任何一個請求都要經過DispatcherServlet進行分發,DispatcherServlet並不對請求進行處理,而是將請求交給HandlerMapping進行對映;HandlerMapping將請求對映為HandlerExecutionChain物件。該物件包含一個Handler物件和多個HandlerInterceptor物件。這裡就體現了一種責任鏈模式的思想;Handler經過一層包裝後變成HandlerAdapter,從而支援多種型別的處理器(Controller),HandlerAdapter將請求交給具體的處理器進行處理,完成後返回ModelAndView;通過ViewResolver對檢視進行解析,並利用Model資料模型對檢視渲染(Render).

DispatcherServlet1

DispatcherServlet繼承關係如下:
DispatcherServlet—>FrameworkServlet—>HttpServletBean—>HttpServlet—>GenericServlet—>Servlet.
HttpServletBean繼承自javax.servlet.http包下的HttpServlet,那麼就先從該類分析:

/**
 * Simple extension of {@link javax.servlet.http.HttpServlet} which treats
 * its config parameters ({@code
init-param} entries within the * {@code servlet} tag in {@code web.xml}) as bean properties. * * <p>A handy superclass for any type of servlet. Type conversion of config * parameters is automatic, with the corresponding setter method getting * invoked with the converted value. It is also possible for
subclasses to * specify required properties. Parameters without matching bean property * setter will simply be ignored. * * <p>This servlet leaves request handling to subclasses, inheriting the default * behavior of HttpServlet ({@code doGet}, {@code doPost}, etc). * * <p>This generic servlet base class has no dependency on the Spring * {@link org.springframework.context.ApplicationContext} concept. Simple * servlets usually don't load their own context but rather access service * beans from the Spring root application context, accessible via the * filter's {@link #getServletContext() ServletContext} (see * {@link org.springframework.web.context.support.WebApplicationContextUtils}). * * <p>The {@link FrameworkServlet} class is a more specific servlet base * class which loads its own application context. FrameworkServlet serves * as direct base class of Spring's full-fledged {@link DispatcherServlet}. * * @author Rod Johnson * @author Juergen Hoeller * @see #addRequiredProperty * @see #initServletBean * @see #doGet * @see #doPost */ @SuppressWarnings("serial") public abstract class HttpServletBean extends HttpServlet implements EnvironmentCapable, EnvironmentAware { }

該類的初始化方法init()

    /**
     * Map config parameters onto bean properties of this servlet, and
     * invoke subclass initialization.
     * @throws ServletException if bean properties are invalid (or required
     * properties are missing), or if subclass initialization fails.
     */
    @Override
    public final void init() throws ServletException {
        if (logger.isDebugEnabled()) {
            logger.debug("Initializing servlet '" + getServletName() + "'");
        }

        // Set bean properties from init parameters.
        try {
            PropertyValues pvs = new ServletConfigPropertyValues(               getServletConfig(), this.requiredProperties);
            BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
            ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
            bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));
            initBeanWrapper(bw);
            bw.setPropertyValues(pvs, true);
        }
        catch (BeansException ex) {
            logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);
            throw ex;
        }

        // Let subclasses do whatever initialization they like.
        initServletBean();

        if (logger.isDebugEnabled()) {
            logger.debug("Servlet '" + getServletName() + "' configured successfully");
        }
    }

try…catch中的內容暫時略過。
之後,該方法呼叫了initServletBean(),該方法在類中進行宣告,但並沒有實現,而是留給子類FrameworkServlet實現。子類FrameworkServlet實現過程如下:

    /**
     * Overridden method of {@link HttpServletBean}, invoked after any bean properties
     * have been set. Creates this servlet's WebApplicationContext.
     */
    @Override
    protected final void initServletBean() throws ServletException {
        getServletContext().log("Initializing Spring FrameworkServlet '" + getServletName() + "'");
        if (this.logger.isInfoEnabled()) {
            this.logger.info("FrameworkServlet '" + getServletName() + "': initialization started");
        }
        long startTime = System.currentTimeMillis();

        try {
            this.webApplicationContext = initWebApplicationContext();
            initFrameworkServlet();
        }
        catch (ServletException ex) {
            this.logger.error("Context initialization failed", ex);
            throw ex;
        }
        catch (RuntimeException ex) {
            this.logger.error("Context initialization failed", ex);
            throw ex;
        }

        if (this.logger.isInfoEnabled()) {
            long elapsedTime = System.currentTimeMillis() - startTime;
            this.logger.info("FrameworkServlet '" + getServletName() + "': initialization completed in " +
                    elapsedTime + " ms");
        }
    }

該方法中依然呼叫了initFrameworkServlet(),該方法在類中定義,並沒有實現,而是留給子類進行實現,不過這次DispatcherServlet並沒有重寫該方法。

    /**
     * This method will be invoked after any bean properties have been set and
     * the WebApplicationContext has been loaded. The default implementation is empty;
     * subclasses may override this method to perform any initialization they require.
     * @throws ServletException in case of an initialization exception
     */
    protected void initFrameworkServlet() throws ServletException {
    }

如上對DispatcherServlet對請求處理的過程分析,可以看出,DispatcherServlet將請求分發給HandlerMapping.
HandlerMapping是位於org.springframework.web.servlet包下的介面.他就定義了一個函式getHandler(HttpServletRequest request).

    /**
     * Return a handler and any interceptors for this request. The choice may be made
     * on request URL, session state, or any factor the implementing class chooses.
     * <p>The returned HandlerExecutionChain contains a handler Object, rather than
     * even a tag interface, so that handlers are not constrained in any way.
     * For example, a HandlerAdapter could be written to allow another framework's
     * handler objects to be used.
     * <p>Returns {@code null} if no match was found. This is not an error.
     * The DispatcherServlet will query all registered HandlerMapping beans to find
     * a match, and only decide there is an error if none can find a handler.
     * @param request current HTTP request
     * @return a HandlerExecutionChain instance containing handler object and
     * any interceptors, or {@code null} if no mapping found
     * @throws Exception if there is an internal error
     */
    HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;

ContextLoaderListener初始化上下文和DispatcherServlet初始化上下文的關係
ContextLoaderListener初始化上下文和DispatcherServlet初始化上下文的關係
DispatcherServlet中有幾個特殊的Bean,這些Bean就是上文中提到的Controller, HandlerMapping, HandlerAdapter, ViewResolver, LocalResolver, ThemeResolver, MultipartResolver.

DispatcherServlet需要在web.xml中進行配置。需要宣告其在容器啟動時初始化,即load-on-startup。同時設定其url-pattern為“/”,表示它攔截所有的請求。
它預設使用WebApplicationContext作為上下文,如果不進行配置,預設會去/WEB-INF/[servlet名字]-servlet.xml中尋找對應的配置檔案。
也可以手動對其進行配置,以覆蓋預設的配置。

引數 描述
contextClass 實現WebApplicationContext介面的類,當前servlet用它來建立上下文,如果沒有指定,預設使用XmlApplicationContext
contextConfigLocation 在此處設定其配置檔案的路徑,通常的做法是classpath: [servlet名字]-servlet.xml表示去根路徑尋找配置檔案
namespace 如果不指定,預設使用[servlet名字]-servlet.xml

相關推薦

SpringMVC架構原始碼分析

SpringMVC 本文在基於SpringMVC 4.3.2.RELEASE版本基礎上,對原始碼進行分析,並探討SpringMVC的原理及用法。 springMVC 整體架構 在瞭解Spring整體架構時,這裡盜用開濤部落格的一張圖。 對該架構

HDFS架構原始碼分析

HDFS 本文主要介紹hadoop2.x版本,分析程式碼主要位於hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server下namenode、datanode與prot

springmvc載入過程原始碼分析

什麼是springmvc springmvc是基於的spring的一個web層框架。  這張圖是spring的架構體系,從中可以看出springmvc和struts一樣都是屬於一個web層框架,是spring框架的一部分。 springmvc和mvc有什麼區別 mvc是一種

springmvc工作原理原始碼分析

一、JavaEE體系結構 二、mvc 設計模式|思想 Model 模型層 (javaBean元件 = 領域模型(javaBean) + 業務層 + 持久層) View 檢視層( html、jsp…) Controller 控制層(委託模型層進行資料處理) 複製程式

技術分享:springmvc工作原理原始碼分析

一、JavaEE體系結構       二、mvc 設計模式|思想       Model 模型層 (javaBean元件 = 領域模型(javaBean) + 業務層 + 持久層) View

004-Ambari架構原始碼結構分析

    微信搜尋公眾號:BearData,關注更多內容。 前幾篇主要是從大體的方向介紹了Ambari,安裝Ambari。本篇主要介紹Ambari的架構及原始碼結構。 基本概念 1. Resource:Ambari把可以被管理的資源的抽象為一個Resource例項,資源可

MyBatis架構設計原始碼分析系列(一):MyBatis架構

如果不太熟悉MyBatis使用的請先參見MyBatis官方文件,這對理解其架構設計和原始碼分析有很大好處。 一、概述 MyBatis並不是一個完整的ORM框架,其官方首頁是這麼介紹自己 The MyBatis data mapper framework makes i

MyBatis架構設計原始碼分析系列 :MyBatis架構

ORM是Object和Relation之間的對映,包括Object->Relation和Relation->Object兩方面。Hibernate是個完整的ORM框架,而MyBatis完成的是Relation->Object,也就是其所說的data mapper framework。關於O

SpringMVC執行流程原始碼分析

# SpringMVC流程及原始碼分析 前言 ​ 學了一遍SpringMVC以後,想著做一個總結,複習一下。複習寫下面的總結的時候才發現,其實自己學的並不徹底、牢固、也沒有學全,視訊跟書本是要結合起來一起,每一位老師的視訊可能提到的東西都不一致,也導致也不是很全面,書本上會講的筆記系統、全面。同時我自己也

SpringMVC學習(二)——SpringMVC架構組件

返回 pin 可能 存在 過程 模式 擴展 攔截器 處理流 相信大家通過前文的學習,已經對SpringMVC這個框架多少有些理解了。還記得上一篇文章中SpringMVC的處理流程嗎? 這個圖大致描述了SpringMVC的整個處理流程,這個流程圖還是相對來說比較容易懂的,下面

mybatis原理,配置介紹原始碼分析

前言 mybatis核心元件有哪些?它是工作原理是什麼? mybatis配置檔案各個引數是什麼含義? mybatis只添加了介面類,沒有實現類,為什麼可以直接查詢呢? mybatis的mapper對映檔案各個引數又是什麼含義? mybatis-spring提供哪些機制簡化了原生mybatis? m

Hibernate使用原始碼分析(一)

Hibernate使用及原始碼分析(一) 本篇文章主要通過hibernate初級使用分析一下原始碼,只是給初學者一點小小的建議,不喜勿噴,謝謝! hibernate環境搭建 簡單使用 原始碼走讀 一 hibernate環境搭建 這裡直接

Android Camera2架構原理分析

請點選轉載地址 前面幾篇主要分析的是android Camera API1.0的架構以及初始化流程,而google在android5.0(Lollipop)開始對Camera的架構進行了調整,為了適應HAL3,新新增實現了CameraDeviceClient,而Came

HashMap實現原理原始碼分析(轉載)

作者: dreamcatcher-cx 出處: <http://www.cnblogs.com/chengxiao/>        雜湊表(hash table)也叫散列表,是一種非常重要的資料結構,應用場景及其豐富,

hog訓練流程原始碼分析

           一、網上一些參考資料        在部落格目標檢測學習_1(用opencv自帶hog實現行人檢測) 中已經使用了opencv自帶的函式detectMultiScale()實

Android非同步訊息處理機制詳解原始碼分析

PS一句:最終還是選擇CSDN來整理髮表這幾年的知識點,該文章平行遷移到CSDN。因為CSDN也支援MarkDown語法了,牛逼啊! 【工匠若水 http://blog.csdn.net/yanbober 轉載煩請註明出處,尊重分享成果】 最近相對來說比較閒,加上養病,所

struts2流程原始碼分析

struts 架構圖 分析這個架構圖,我們可以從4個部分,也就struts訪問的4個階段的流程來分析 這4個階段包括:Action對映、Action轉發、Action執行、結果返回 首先是Action對映階段 當請求到來的時候,首先是struts的核心過濾器接收到請求,然後通過ActionMapp

併發程式設計(三)—— ReentrantLock實現原理原始碼分析

  ReentrantLock是Java併發包中提供的一個可重入的互斥鎖。ReentrantLock和synchronized在基本用法,行為語義上都是類似的,同樣都具有可重入性。只不過相比原生的Synchronized,ReentrantLock增加了一些高階的擴充套件功能,比如它可以實現公平鎖,同時也可以

Spring Data之Repository建立原始碼分析

背景 在上一篇文章Spring Data之EntityManager建立及原始碼分析介紹了EntityManager的建立過程,我們使用Spring Data JPA開發時一般是通過自定義一個例如UserRepository的介面,然後繼承JpaRepository或者CrudRepos

Spring Data之EntityManager建立原始碼分析

背景 前一篇文章介紹了EntityManagerFactory的建立過程,有了EntityManagerFactory接下來就是要獲取EntityManager了,但EntityManager的建立不再是通過@Conditional註解,而是使用的@PersistenceContext註