天天看點

SSM-SpringMVC-SpringMVC初始化-初始化映射請求上下文SSM-SpringMVC-SpringMVC初始化-初始化映射請求上下文

SSM-SpringMVC-SpringMVC初始化-初始化映射請求上下文

​ 映射請求上下文是通過DispatcherServlet初始化的,根據自己的需要配置啟動時初始化,或者等待使用者第一次請求時進行初始化。在WEB工程中沒有注冊ContextLoaderListener,這時DispatcherServle就會在其初始化對SpringIOC進行初始化

選擇什麼時候初始化:

​ 大部分情況下,讓DispatcherServle在伺服器啟動期間就完成SpringIoc容器初始化,可以在WEB容器剛開始就對其初始化,在整個WEB的初始化中,不隻是DispatcherServle需要得到SpringIOC資源,其他元件也需要,是以大部分情況下都建議使用ContextLoaderListener進行初始化

DispatcherServle設計:

SSM-SpringMVC-SpringMVC初始化-初始化映射請求上下文SSM-SpringMVC-SpringMVC初始化-初始化映射請求上下文

是一個可以加載加載WEB容器中的Servlet

​ web容器對于servlet的初始化,首先調用其init初始化方法,對于DispactherServlet也是如此,該方法位于父類HttpServletBean

public final void init() throws ServletException {
    PropertyValues pvs = new HttpServletBean.ServletConfigPropertyValues(this.getServletConfig(), this.requiredProperties);
    if (!pvs.isEmpty()) {
        //根據參數初始化 bean 的屬性
        try {
            BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
            ResourceLoader resourceLoader = new ServletContextResourceLoader(this.getServletContext());
            bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, this.getEnvironment()));
            this.initBeanWrapper(bw);
            bw.setPropertyValues(pvs, true);
        } catch (BeansException var4) {
            if (this.logger.isErrorEnabled()) {
                this.logger.error("Failed to set bean properties on servlet '" + this.getServletName() + "'", var4);
            }

            throw var4;
        }
    }
	//交由子類去實作
    this.initServletBean();
}
           

上面代碼中,可以看到initServletBean方法,在FrameworkServlet類中也能看見該方法,是以它覆寫了FrameworkServlet類中的initServletBean方法。

FrameworkServlet中的initServletBean方法

protected final void initServletBean() throws ServletException {
    this.getServletContext().log("Initializing Spring " + this.getClass().getSimpleName() + " '" + this.getServletName() + "'");
    if (this.logger.isInfoEnabled()) {
        this.logger.info("Initializing Servlet '" + this.getServletName() + "'");
    }

    long startTime = System.currentTimeMillis();

    try {
        //初始化SpringIOC容器
        this.webApplicationContext = this.initWebApplicationContext();
        this.initFrameworkServlet();
    } catch (RuntimeException | ServletException var4) {
        this.logger.error("Context initialization failed", var4);
        throw var4;
    }

    if (this.logger.isDebugEnabled()) {
        String value = this.enableLoggingRequestDetails ? "shown which may lead to unsafe logging of potentially sensitive data" : "masked to prevent unsafe logging of potentially sensitive data";
        this.logger.debug("enableLoggingRequestDetails='" + this.enableLoggingRequestDetails + "': request parameters and headers will be " + value);
    }

    if (this.logger.isInfoEnabled()) {
        this.logger.info("Completed initialization in " + (System.currentTimeMillis() - startTime) + " ms");
    }

}
           

方法initWebApplicationContext:

protected WebApplicationContext initWebApplicationContext() {
    WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
    WebApplicationContext wac = null;
    //判斷是否已經被初始化
    if (this.webApplicationContext != null) {
        //如果webIOC容器已經在啟動的時候建立,那麼久沿用它
        wac = this.webApplicationContext;
        if (wac instanceof ConfigurableWebApplicationContext) {
            ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext)wac;
            if (!cwac.isActive()) {
                //如果SPirng IOC容器還沒有重新整理,那麼就進行重新整理父類容器上下文,設定id等操作
                //處理父容器為空的情況
                if (cwac.getParent() == null) {
                    cwac.setParent(rootContext);
                }

                this.configureAndRefreshWebApplicationContext(cwac);
            }
        }
    }
	
    //沒有被初始化,則查找是否存在的Spring Web IoC容器
    if (wac == null) {
        wac = this.findWebApplicationContext();
    }
    
    //沒有初始化,也沒有找到存在的Spring Web Ioc容器,則DispatcherServlet自己建立
    if (wac == null) {
        wac = this.createWebApplicationContext(rootContext);
    }

    //當onRefresh方法沒有被調用過,執行onRefresh方法
    if (!this.refreshEventReceived) {
        synchronized(this.onRefreshMonitor) {
            this.onRefresh(wac);
        }
    }

    if (this.publishContext) {
        //作為Servlet的上下文屬性釋出IOC容器
        String attrName = this.getServletContextAttributeName();
        this.getServletContext().setAttribute(attrName, wac);
    }

    return wac;
}
           

​ 當IOC容器沒有對應初始化,DispatcherServlet會嘗試去初始化它,最後排程onRefresh方法,是DispatcherServlet十分關注的方法,該方法就在DispatcherServlet中

onRefresh方法在DispatcherServlet代碼中如下:

protected void onRefresh(ApplicationContext context) {
    this.initStrategies(context);
}
           

其中調用了自身的initStrategies方法:

protected void initStrategies(ApplicationContext context) {
    //初始化檔案的解析
    this.initMultipartResolver(context);
    //本地解析化
    this.initLocaleResolver(context);
    //主題解析
    this.initThemeResolver(context);
    //處理器解析
    this.initHandlerMappings(context);
    //處理器的擴充卡
    this.initHandlerAdapters(context);
    //Handler的異常處了解析器
    this.initHandlerExceptionResolvers(context);
    //當處理器沒有傳回邏輯視圖名等相關資訊時,自動将請求 URL 映射為邏輯視圖名
    this.initRequestToViewNameTranslator(context);
    //視圖邏輯名稱轉化器,即允許傳回邏輯視圖名稱,然後它會找到真實的視圖
    this.initViewResolvers(context);
    //這是一個關注Falsh開發的Map管理器
    this.initFlashMapManager(context);
}
           
  • MultipartResolver:檔案解析器,用于支援伺服器的檔案上傳
  • LocaleResolver:國際化解析器,可以提供國際化的功能
  • ThemeResolver:主題解析器,類似軟體皮膚的轉換功能
  • HandlerMapping:會 包裝使用者提供一個控制器的方法和對它的一些攔截,通過調用他就能運作控制器
  • handlerAdapter:處理擴充卡,因為處理器會在不同的上下文運作,SpringMVC會先找到合适的擴充卡,然後運作處理器服務方法
  • HandlerExceptionResolver:處理器異常解析器,當産生異常,可以通過異常解析器來處理
  • RequestTo ViewNameTranslator :視圖邏輯名稱轉換器,在控制前中傳回一個視圖的名稱,通過它可以找到實際的視圖,當處理器沒有傳回邏輯視圖名等相關資訊時,自動将請求URL映射為邏輯視圖名
  • ViewResolver:視圖解析器,當控制器傳回後,通過視圖解析器會把邏輯視圖名稱進行解析,然後定位實際視圖

器來處理

  • RequestTo ViewNameTranslator :視圖邏輯名稱轉換器,在控制前中傳回一個視圖的名稱,通過它可以找到實際的視圖,當處理器沒有傳回邏輯視圖名等相關資訊時,自動将請求URL映射為邏輯視圖名
  • ViewResolver:視圖解析器,當控制器傳回後,通過視圖解析器會把邏輯視圖名稱進行解析,然後定位實際視圖

​ 上面是Spring MVC主要的元件的初始化,實際,這些元件DispatcherServlet會根據配置檔案DispatcherServlet.properties進行初始化

繼續閱讀