前面幾篇文章都是針對於SpringMVC中的具體組件進行源碼分析的;本文主要用於補充記錄一下關於SpringMVC中九大組件的學習。這個會牽扯出除以前的幾篇HandlerMapping
以外的其餘一些基礎組件。css
以前簡單的有介紹過DispatcherServlet
這個類的體系結構,此處就再也不贅述了。在DispatcherServlet
類中,其在mvc子容器進行初始化時就會完成對九大組件的初始化工做,具體哪九大組件後面會慢慢說到。先來看下在DispatcherServlet
中是經過哪些方法來完成初始化工做的,先貼一段代碼:html
protected void onRefresh(ApplicationContext context) {
this.initStrategies(context);
}
protected void initStrategies(ApplicationContext context) {
this.initMultipartResolver(context);
this.initLocaleResolver(context);
this.initThemeResolver(context);
this.initHandlerMappings(context);
this.initHandlerAdapters(context);
this.initHandlerExceptionResolvers(context);
this.initRequestToViewNameTranslator(context);
this.initViewResolvers(context);
this.initFlashMapManager(context);
}
複製代碼
上面代碼中的onRefresh
方法就是DispatcherServlet
的入口方法。在onRefresh
中又經過調用initStrategies
方法來將各個組件的初始化邏輯進行整合,我的理解其實就是策略套策略,在一個就是職責也明確。java
在initStrategies
方法中又經過調用組件各自的初始化方法來完成具體的初始化工做。從這個地方其實就能夠清楚的看出SpringMVC中的9個組件名稱了。下面就來捋一捋這九大組件的基本職責。bash
關於handlermapping在下面幾篇文章中作過一些基本介紹,可是還不是很全,對於handlermapping的子類尚未分析完,這個會後期更新的。session
對於HandlerMapping
來講,其做用就是根據request
找到相應的處理器Handler
和Intecepter
攔截器。具體細節參數上面第一篇文章。mvc
若是說HandlerMapping
是一支筆,那麼HandlerAdapter
就是用筆的人。也就是說HandlerAdapter
就是使用處理器幹活的人。爲何呢?來看下代碼:app
public interface HandlerAdapter {
boolean supports(Object var1);
ModelAndView handle(HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception;
long getLastModified(HttpServletRequest var1, Object var2);
}
複製代碼
是否是一目瞭然了,在HandlerAdapter
接口中提供了handle
這樣一個方法,參數中Object handler第三個參數其實就是一個處理器,那咱們就知道了,handle
方法就是使用handler
來處理邏輯的。處理以後返回一個ModelAndView
。jsp
這個是SpringMVC
中的異常處理組件,HandlerExceptionResolver
這個組件的做用就是根據異常設置ModelAndView
,而後再將處理結果交給render
方法進行渲染。固然render
也僅僅只是負責將ModelAndView
渲染成頁面,ModelAndView
的具體來源它不關心。源碼分析
這裏須要說明一下,加入在渲染過程當中發生異常怎麼辦?從上面的分析咱們能夠清楚的知道,HandlerExceptionResolver
這個組件對異常的處理結果是ModelAndView
,而後再由render
方法進行渲染,也就是說HandlerExceptionResolver
是在渲染以前工做的,所以渲染過程當中發生異常,HandlerExceptionResolver
是不會處理的。post
public interface HandlerExceptionResolver {
ModelAndView resolveException(HttpServletRequest var1, HttpServletResponse var2, Object var3, Exception var4);
}
複製代碼
在HandlerExceptionResolver
中也只有一個方法,這個方法就是從異常中解析出ModelAndView
。
ViewResolver
的做用是將String
類型的邏輯視圖根據local解析爲View
視圖的。下面是ViewResolver
的源碼接口定義:
public interface ViewResolver {
View resolveViewName(String viewName, Locale local) throws Exception;
}
複製代碼
從代碼中能夠看到,在ViewResolver
中也是隻有一個方法,從resolveViewName
方法的參數和返回結果就很好的解釋了其做用。
View
其實是用來渲染頁面的,也就是說將程序返回的結果填入到具體的模板裏面,生成具體的視圖文件,好比:jsp,ftl,html等。
可是這裏又會牽扯出兩個問題:
固然,這兩個問題也就是本小節說的ViewResolver
須要解決的問題。大致分爲兩種:
上面兩種是用的最多的兩種,InternalResourceViewResolver
用來解析jsp,而FreeMarkerViewResolver
則是針對FreeMarker。
BeanNameViewResolver
須要同時使用視圖名和對應的local來解析視圖。它須要將每個視圖名和對應的視圖類型配置到相應的properties文件中。(後面講組件實現細節時給出列子)
XmlViewResolver
XmlViewResolver和BeanNameViewResolver有點差很少,BeanNameViewResolver使用的是xml格式的配置文件。
ResourceBundleViewResolver
這個其實就是根據viewName從Spring容器中查找bean,再根據這個bean來找到對應的視圖。
在上面的ViewResolver
中提到,解析視圖須要兩個參數,一個是String類型的邏輯視圖名,另一個是local。LocalResolver
的做用就是從request中解析出local的。
public interface LocaleResolver {
Locale resolveLocale(HttpServletRequest request);
void setLocale(HttpServletRequest request, HttpServletResponse response, Locale local);
}
複製代碼
第一個方法是從request中解析出local,第二個方法是將local設置到request中。
關於local大多數狀況下都是用來作國際化處理的。
解析主題的。這個我平時除了SpringMVC本身提供的功能外,不多本身去擴展使用,即便是換主題也沒有作過。不過既然存在確定是有存在的緣由的。對於咱們常見的網頁界面活着手機界面來講,一套主題無非就是換一套圖片,活着css樣式文件等等。咱們經過ThemeResolver
這個就能夠實現這樣的功能。具體使用其實也就是配一套properties文件供系統在不一樣的時候讀取切換;固然使用這個也是能夠實現國際化的。
public interface ThemeResolver {
String resolveThemeName(HttpServletRequest request);
void setThemeName(HttpServletRequest request, HttpServletResponse response, String themeName);
}
複製代碼
這個其實仍是挺有意思的,就是將request請求轉換爲視圖名稱。
public interface RequestToViewNameTranslator {
String getViewName(HttpServletRequest request) throws Exception;
}
複製代碼
RequestToViewNameTranslator
只有一個默認的實現類DefaultRequestToViewNameTranslator
。
在DefaultRequestToViewNameTranslator
具體實現了getViewName(HttpServletRequest request)方法:
public String getViewName(HttpServletRequest request) {
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
return this.prefix + this.transformPath(lookupPath) + this.suffix;
}
複製代碼
主要是委派給urlPathHelper幫助類獲得請求的後綴名稱,好比經過 請求路徑好比/glmapper/login.do轉換獲得/login.do ;具體怎麼轉換成視圖也會在後面的組件介紹中給出具體的例子。
這個相應小夥伴們也不陌生,作網站多多少少會涉及到文件上傳。MultipartResolver
就是用來處理上傳請求的。其處理方式就是將request包裝成MultipartHttpServletRequest
。而後咱們就能夠用MultipartHttpServletRequest
這個直接調用getFile獲取的文件了。
這個在redirect是進行參數傳遞須要用到。
public interface FlashMapManager {
FlashMap retrieveAndUpdate(HttpServletRequest request, HttpServletResponse response);
void saveOutputFlashMap(FlashMap flashMap, HttpServletRequest request, HttpServletResponse response);
}
複製代碼
retrieveAndUpdate
這個方法是用來恢復參數的,對於恢復過的和超時的參數將都會被刪除掉。
saveOutputFlashMap
這個方法是用來保存參數的。
FlashMapManager
的默認實現機制中參數的存儲是放在session中的。我以前在一個項目中就有遇到過這種狀況,對於一些咱們不想暴露在url中的參數,在進行請求轉發時,可使用@RedirectAttributes將參數保存,而後在下一個處理器中獲取到。
本篇主要是來對九大組件作一個籠統的介紹,細節實現及案例均不涉及;在後續的SpringMVC源碼系列中對各個組件的實現細節分析時再一探究竟吧。