MVC 是一種設計模式.前端
MVC 的原理圖以下:java
SpringMVC 框架是以請求爲驅動,圍繞 Servlet 設計,將請求發給控制器,而後經過模型對象,分派器來展現請求結果視圖。其中核心類是 DispatcherServlet,它是一個 Servlet,頂層是實現的Servlet接口。web
須要在 web.xml 中配置 DispatcherServlet 。而且須要配置 Spring 監聽器ContextLoaderListenerspring
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet </servlet-class> <!-- 若是不設置init-param標籤,則必須在/WEB-INF/下建立xxx-servlet.xml文件,其中xxx是servlet-name中配置的名稱。 --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/springmvc-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
簡單來講:後端
客戶端發送請求-> 前端控制器 DispatcherServlet 接受客戶端請求 -> 找處處理器映射 HandlerMapping 解析請求對應的 Handler-> HandlerAdapter 會根據 Handler 來調用真正的處理器開處理請求,並處理相應的業務邏輯 -> 處理器返回一個模型視圖 ModelAndView -> 視圖解析器進行解析 -> 返回一個視圖對象->前端控制器 DispatcherServlet 渲染數據(Moder)->將獲得視圖對象返回給用戶設計模式
以下圖所示: 瀏覽器
上圖的一個筆誤的小問題:Spring MVC 的入口函數也就是前端控制器 DispatcherServlet 的做用是接收請求,響應結果。mvc
流程說明(重要):app
(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 返回給請求者(瀏覽器)
一、前端控制器DispatcherServlet(不須要工程師開發),由框架提供(重要)
做用:Spring MVC 的入口函數。接收請求,響應結果,至關於轉發器,中央處理器。有了 DispatcherServlet 減小了其它組件之間的耦合度。用戶請求到達前端控制器,它就至關於mvc模式中的c,DispatcherServlet是整個流程控制的中心,由它調用其它組件處理用戶的請求,DispatcherServlet的存在下降了組件之間的耦合性。
二、處理器映射器HandlerMapping(不須要工程師開發),由框架提供
做用:根據請求的url查找Handler。HandlerMapping負責根據用戶請求找到Handler即處理器(Controller),SpringMVC提供了不一樣的映射器實現不一樣的映射方式,例如:配置文件方式,實現接口方式,註解方式等。
三、處理器適配器HandlerAdapter
做用:按照特定規則(HandlerAdapter要求的規則)去執行Handler 經過HandlerAdapter對處理器進行執行,這是適配器模式的應用,經過擴展適配器能夠對更多類型的處理器進行執行。
四、處理器Handler(須要工程師開發)
注意:編寫Handler時按照HandlerAdapter的要求去作,這樣適配器才能夠去正確執行Handler Handler 是繼DispatcherServlet前端控制器的後端控制器,在DispatcherServlet的控制下Handler對具體的用戶請求進行處理。 因爲Handler涉及到具體的用戶業務請求,因此通常狀況須要工程師根據業務需求開發Handler。
五、視圖解析器View resolver(不須要工程師開發),由框架提供
做用:進行視圖解析,根據邏輯視圖名解析成真正的視圖(view) View Resolver負責將處理結果生成View視圖,View Resolver首先根據邏輯視圖名解析成物理視圖名即具體的頁面地址,再生成View視圖對象,最後對View進行渲染將處理結果經過頁面展現給用戶。 springmvc框架提供了不少的View視圖類型,包括:jstlView、freemarkerView、pdfView等。 通常狀況下須要經過頁面標籤或頁面模版技術將模型數據經過頁面展現給用戶,須要由工程師根據業務需求開發具體的頁面。
六、視圖View(須要工程師開發)
View是一個接口,實現類支持不一樣的View類型(jsp、freemarker、pdf...)
注意:處理器Handler(也就是咱們日常說的Controller控制器)以及視圖層view都是須要咱們本身手動開發的。其餘的一些組件好比:前端控制器DispatcherServlet、處理器映射器HandlerMapping、處理器適配器HandlerAdapter等等都是框架提供給咱們的,不須要本身手動開發。
首先看下源碼:
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<HandlerMapping> handlerMappings; /** List of HandlerAdapters used by this servlet */ private List<HandlerAdapter> handlerAdapters; /** List of HandlerExceptionResolvers used by this servlet */ private List<HandlerExceptionResolver> handlerExceptionResolvers; /** RequestToViewNameTranslator used by this servlet */ private RequestToViewNameTranslator viewNameTranslator; private FlashMapManager flashMapManager; /** List of ViewResolvers used by this servlet */ private List<ViewResolver> 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:
在Web MVC框架中,每一個DispatcherServlet都擁本身的WebApplicationContext,它繼承了ApplicationContext。WebApplicationContext包含了其上下文和Servlet實例之間共享的全部的基礎框架beans。
HandlerMapping
HandlerMapping接口處理請求的映射HandlerMapping接口的實現類:
HandlerAdapter
HandlerAdapter接口-處理請求映射
AnnotationMethodHandlerAdapter:經過註解,把請求URL映射到Controller類的方法上。
HandlerExceptionResolver
HandlerExceptionResolver接口-異常處理接口
ViewResolver
ViewResolver接口解析View視圖。
UrlBasedViewResolver類 經過配置文件,把一個視圖名交給到一個View來處理。 QQ討論羣組:984370849 706564342 歡迎加入討論
想要深刻學習的同窗們能夠加入QQ羣討論,有全套資源分享,經驗探討,沒錯,咱們等着你,分享互相的故事!