SpringMVC 工作原理詳解

本文整理自網絡,原文出處暫不知,對原文做了較大的改動,在此說明!

先來看一下什麼是 MVC 模式

MVC 是一種設計模式.

MVC 的原理圖如下:

SpringMVC 工作原理詳解

SpringMVC 簡單介紹

SpringMVC 框架是以請求為驅動,圍繞 Servlet 設計,將請求發給控制器,然後通過模型對象,分派器來展示請求結果視圖。其中核心類是 DispatcherServlet,它是一個 Servlet,頂層是實現的Servlet接口。

SpringMVC 使用

需要在 web.xml 中配置 DispatcherServlet 。並且需要配置 Spring 監聽器ContextLoaderListener


org.springframework.web.context.ContextLoaderListener



springmvc
org.springframework.web.servlet.DispatcherServlet



contextConfigLocation
classpath:spring/springmvc-servlet.xml

1


springmvc
/

SpringMVC 工作原理(重要)

簡單來說:

客戶端發送請求-> 前端控制器 DispatcherServlet 接受客戶端請求 -> 找到處理器映射 HandlerMapping 解析請求對應的 Handler-> HandlerAdapter 會根據 Handler 來調用真正的處理器開處理請求,並處理相應的業務邏輯 -> 處理器返回一個模型視圖 ModelAndView -> 視圖解析器進行解析 -> 返回一個視圖對象->前端控制器 DispatcherServlet 渲染數據(Moder)->將得到視圖對象返回給用戶

如下圖所示:

SpringMVC 工作原理詳解

SpringMVC運行原理

上圖的一個筆誤的小問題:Spring MVC 的入口函數也就是前端控制器 DispatcherServlet 的作用是接收請求,響應結果。

流程說明(重要):

(1)客戶端(瀏覽器)發送請求,直接請求到 DispatcherServlet。

(2)DispatcherServlet 根據請求信息調用 HandlerMapping,解析請求對應的 Handler。

(3)解析到對應的 Handler(也就是我們平常說的 Controller 控制器)後,開始由 HandlerAdapter 適配器處理。

(4)HandlerAdapter 會根據 Handler 來調用真正的處理器開處理請求,並處理相應的業務邏輯。

(5)處理器處理完業務後,會返回一個 ModelAndView 對象,Model 是返回的數據對象,View 是個邏輯上的 View。

(6)ViewResolver 會根據邏輯 View 查找實際的 View。

(7)DispaterServlet 把返回的 Model 傳給 View(視圖渲染)。

(8)把 View 返回給請求者(瀏覽器)

SpringMVC 重要組件說明

1、前端控制器DispatcherServlet(不需要工程師開發),由框架提供(重要)

作用:Spring MVC 的入口函數。接收請求,響應結果,相當於轉發器,中央處理器。有了 DispatcherServlet 減少了其它組件之間的耦合度。用戶請求到達前端控制器,它就相當於mvc模式中的c,DispatcherServlet是整個流程控制的中心,由它調用其它組件處理用戶的請求,DispatcherServlet的存在降低了組件之間的耦合性。

2、處理器映射器HandlerMapping(不需要工程師開發),由框架提供

作用:根據請求的url查找Handler。HandlerMapping負責根據用戶請求找到Handler即處理器(Controller),SpringMVC提供了不同的映射器實現不同的映射方式,例如:配置文件方式,實現接口方式,註解方式等。

3、處理器適配器HandlerAdapter

作用:按照特定規則(HandlerAdapter要求的規則)去執行Handler

通過HandlerAdapter對處理器進行執行,這是適配器模式的應用,通過擴展適配器可以對更多類型的處理器進行執行。

4、處理器Handler(需要工程師開發)

注意:編寫Handler時按照HandlerAdapter的要求去做,這樣適配器才可以去正確執行Handler

Handler 是繼DispatcherServlet前端控制器的後端控制器,在DispatcherServlet的控制下Handler對具體的用戶請求進行處理。

由於Handler涉及到具體的用戶業務請求,所以一般情況需要工程師根據業務需求開發Handler。

5、視圖解析器View resolver(不需要工程師開發),由框架提供

作用:進行視圖解析,根據邏輯視圖名解析成真正的視圖(view)

View Resolver負責將處理結果生成View視圖,View Resolver首先根據邏輯視圖名解析成物理視圖名即具體的頁面地址,再生成View視圖對象,最後對View進行渲染將處理結果通過頁面展示給用戶。 springmvc框架提供了很多的View視圖類型,包括:jstlView、freemarkerView、pdfView等。

一般情況下需要通過頁面標籤或頁面模版技術將模型數據通過頁面展示給用戶,需要由工程師根據業務需求開發具體的頁面。

6、視圖View(需要工程師開發)

View是一個接口,實現類支持不同的View類型(jsp、freemarker、pdf…)

注意:處理器Handler(也就是我們平常說的Controller控制器)以及視圖層view都是需要我們自己手動開發的。其他的一些組件比如:前端控制器DispatcherServlet、處理器映射器HandlerMapping、處理器適配器HandlerAdapter等等都是框架提供給我們的,不需要自己手動開發。

DispatcherServlet詳細解析

首先看下源碼:

package org.springframework.web.servlet;
@SuppressWarnings("serial")
public class DispatcherServlet extends FrameworkServlet {
public static final String MULTIPART_RESOLVER_BEAN_NAME = "multipartResolver";
public static final String LOCALE_RESOLVER_BEAN_NAME = "localeResolver";
public static final String THEME_RESOLVER_BEAN_NAME = "themeResolver";
public static final String HANDLER_MAPPING_BEAN_NAME = "handlerMapping";
public static final String HANDLER_ADAPTER_BEAN_NAME = "handlerAdapter";
public static final String HANDLER_EXCEPTION_RESOLVER_BEAN_NAME = "handlerExceptionResolver";
public static final String REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME = "viewNameTranslator";
public static final String VIEW_RESOLVER_BEAN_NAME = "viewResolver";
public static final String FLASH_MAP_MANAGER_BEAN_NAME = "flashMapManager";
public static final String WEB_APPLICATION_CONTEXT_ATTRIBUTE = DispatcherServlet.class.getName() + ".CONTEXT";
public static final String LOCALE_RESOLVER_ATTRIBUTE = DispatcherServlet.class.getName() + ".LOCALE_RESOLVER";
public static final String THEME_RESOLVER_ATTRIBUTE = DispatcherServlet.class.getName() + ".THEME_RESOLVER";
public static final String THEME_SOURCE_ATTRIBUTE = DispatcherServlet.class.getName() + ".THEME_SOURCE";
public static final String INPUT_FLASH_MAP_ATTRIBUTE = DispatcherServlet.class.getName() + ".INPUT_FLASH_MAP";
public static final String OUTPUT_FLASH_MAP_ATTRIBUTE = DispatcherServlet.class.getName() + ".OUTPUT_FLASH_MAP";
public static final String FLASH_MAP_MANAGER_ATTRIBUTE = DispatcherServlet.class.getName() + ".FLASH_MAP_MANAGER";
public static final String EXCEPTION_ATTRIBUTE = DispatcherServlet.class.getName() + ".EXCEPTION";
public static final String PAGE_NOT_FOUND_LOG_CATEGORY = "org.springframework.web.servlet.PageNotFound";
private static final String DEFAULT_STRATEGIES_PATH = "DispatcherServlet.properties";
protected static final Log pageNotFoundLogger = LogFactory.getLog(PAGE_NOT_FOUND_LOG_CATEGORY);

private static final Properties defaultStrategies;
static {
try {
ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);
defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
}
catch (IOException ex) {
throw new IllegalStateException("Could not load 'DispatcherServlet.properties': " + ex.getMessage());
}
}
/** Detect all HandlerMappings or just expect "handlerMapping" bean? */
private boolean detectAllHandlerMappings = true;
/** Detect all HandlerAdapters or just expect "handlerAdapter" bean? */
private boolean detectAllHandlerAdapters = true;
/** Detect all HandlerExceptionResolvers or just expect "handlerExceptionResolver" bean? */
private boolean detectAllHandlerExceptionResolvers = true;
/** Detect all ViewResolvers or just expect "viewResolver" bean? */
private boolean detectAllViewResolvers = true;
/** Throw a NoHandlerFoundException if no Handler was found to process this request? **/
private boolean throwExceptionIfNoHandlerFound = false;
/** Perform cleanup of request attributes after include request? */
private boolean cleanupAfterInclude = true;
/** MultipartResolver used by this servlet */
private MultipartResolver multipartResolver;
/** LocaleResolver used by this servlet */
private LocaleResolver localeResolver;
/** ThemeResolver used by this servlet */
private ThemeResolver themeResolver;
/** List of HandlerMappings used by this servlet */
private List handlerMappings;
/** List of HandlerAdapters used by this servlet */
private List handlerAdapters;
/** List of HandlerExceptionResolvers used by this servlet */
private List handlerExceptionResolvers;
/** RequestToViewNameTranslator used by this servlet */
private RequestToViewNameTranslator viewNameTranslator;
private FlashMapManager flashMapManager;
/** List of ViewResolvers used by this servlet */
private List viewResolvers;
public DispatcherServlet() {
super();
}
public DispatcherServlet(WebApplicationContext webApplicationContext) {
super(webApplicationContext);
}
@Override

protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
}
}

DispatcherServlet類中的屬性beans:

  • HandlerMapping:用於handlers映射請求和一系列的對於攔截器的前處理和後處理,大部分用@Controller註解。
  • HandlerAdapter:幫助DispatcherServlet處理映射請求處理程序的適配器,而不用考慮實際調用的是 哪個處理程序。- - -
  • ViewResolver:根據實際配置解析實際的View類型。
  • ThemeResolver:解決Web應用程序可以使用的主題,例如提供個性化佈局。
  • MultipartResolver:解析多部分請求,以支持從HTML表單上傳文件。-
  • FlashMapManager:存儲並檢索可用於將一個請求屬性傳遞到另一個請求的input和output的FlashMap,通常用於重定向。

在Web MVC框架中,每個DispatcherServlet都擁自己的WebApplicationContext,它繼承了ApplicationContext。WebApplicationContext包含了其上下文和Servlet實例之間共享的所有的基礎框架beans。

HandlerMapping

SpringMVC 工作原理詳解

HandlerMapping

HandlerMapping接口處理請求的映射HandlerMapping接口的實現類:

  • SimpleUrlHandlerMapping類通過配置文件把URL映射到Controller類。
  • DefaultAnnotationHandlerMapping類通過註解把URL映射到Controller類。

HandlerAdapter

SpringMVC 工作原理詳解

HandlerAdapter

HandlerAdapter接口-處理請求映射

AnnotationMethodHandlerAdapter:通過註解,把請求URL映射到Controller類的方法上。

HandlerExceptionResolver

SpringMVC 工作原理詳解

HandlerExceptionResolver

HandlerExceptionResolver接口-異常處理接口

  • SimpleMappingExceptionResolver通過配置文件進行異常處理。
  • AnnotationMethodHandlerExceptionResolver:通過註解進行異常處理。

ViewResolver

SpringMVC 工作原理詳解

ViewResolver

ViewResolver接口解析View視圖。

UrlBasedViewResolver類 通過配置文件,把一個視圖名交給到一個View來處理。


分享到:


相關文章: