SpringMVC架構及原始碼分析
SpringMVC
本文在基於SpringMVC 4.3.2.RELEASE版本基礎上,對原始碼進行分析,並探討SpringMVC的原理及用法。
springMVC
整體架構
在瞭解Spring整體架構時,這裡盜用開濤部落格的一張圖。
對該架構流程進行簡單的分析如下:
任何一個請求都要經過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初始化上下文的關係
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註