SpringMVC源碼系列:九大組件小記

前面幾篇文章都是針對於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在下面幾篇文章中作過一些基本介紹,可是還不是很全,對於handlermapping的子類尚未分析完,這個會後期更新的。session

對於HandlerMapping來講,其做用就是根據request找到相應的處理器HandlerIntecepter攔截器。具體細節參數上面第一篇文章。mvc

HandlerAdapter

若是說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來處理邏輯的。處理以後返回一個ModelAndViewjsp

HandlerExceptionResolver

這個是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

ViewResolver的做用是將String類型的邏輯視圖根據local解析爲View視圖的。下面是ViewResolver的源碼接口定義:

public interface ViewResolver {
    View resolveViewName(String viewName, Locale local) throws Exception;
}
複製代碼

從代碼中能夠看到,在ViewResolver中也是隻有一個方法,從resolveViewName方法的參數和返回結果就很好的解釋了其做用。

  • viewName String類型的視圖名
  • local 區域,能夠用來作國際化。

View其實是用來渲染頁面的,也就是說將程序返回的結果填入到具體的模板裏面,生成具體的視圖文件,好比:jsp,ftl,html等。

可是這裏又會牽扯出兩個問題:

  • 用什麼模板?
  • 參數怎麼填入?

固然,這兩個問題也就是本小節說的ViewResolver須要解決的問題。大致分爲兩種:

針對單一視圖類型的解析器

  • InternalResourceViewResolver
  • FreeMarkerViewResolver

上面兩種是用的最多的兩種,InternalResourceViewResolver用來解析jsp,而FreeMarkerViewResolver則是針對FreeMarker。

針對同時解析多種類型視圖的解析器

  • BeanNameViewResolver

    須要同時使用視圖名和對應的local來解析視圖。它須要將每個視圖名和對應的視圖類型配置到相應的properties文件中。(後面講組件實現細節時給出列子)

  • XmlViewResolver

    XmlViewResolver和BeanNameViewResolver有點差很少,BeanNameViewResolver使用的是xml格式的配置文件。

  • ResourceBundleViewResolver

    這個其實就是根據viewName從Spring容器中查找bean,再根據這個bean來找到對應的視圖。

LocalResolver

在上面的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大多數狀況下都是用來作國際化處理的。

ThemeResolver

解析主題的。這個我平時除了SpringMVC本身提供的功能外,不多本身去擴展使用,即便是換主題也沒有作過。不過既然存在確定是有存在的緣由的。對於咱們常見的網頁界面活着手機界面來講,一套主題無非就是換一套圖片,活着css樣式文件等等。咱們經過ThemeResolver這個就能夠實現這樣的功能。具體使用其實也就是配一套properties文件供系統在不一樣的時候讀取切換;固然使用這個也是能夠實現國際化的。

public interface ThemeResolver {
    String resolveThemeName(HttpServletRequest request);

    void setThemeName(HttpServletRequest request, HttpServletResponse response, String themeName);
}
複製代碼

RequestToViewNameTranslator

這個其實仍是挺有意思的,就是將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

這個相應小夥伴們也不陌生,作網站多多少少會涉及到文件上傳。MultipartResolver就是用來處理上傳請求的。其處理方式就是將request包裝成MultipartHttpServletRequest。而後咱們就能夠用MultipartHttpServletRequest這個直接調用getFile獲取的文件了。

FlashMapManager

這個在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源碼系列中對各個組件的實現細節分析時再一探究竟吧。

相關文章
相關標籤/搜索