springmvc DispatchServlet初始化九大加載策略(一)


由於篇幅較長,因此分三篇進行講解:

springmvc DispatchServlet初始化九大加載策略(一)

springmvc DispatchServlet初始化九大加載策略(二)

springmvc DispatchServlet初始化九大加載策略(三)

 

正文

SpringMVC 容器初始化時,

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);
}

 

 

1. initMultipartResolver 文件上傳

源碼:

this.multipartResolver = (MultipartResolver)context.getBean("multipartResolver", MultipartResolver.class);

MultipartResolver接口定義如下:

public interface MultipartResolver {
    // 檢查請求頭是否包含文件流上傳
    boolean isMultipart(HttpServletRequest var1);
    
    // 文件流上傳請求解析方法,解析后封裝在 MultipartHttpServletRequest 對象中
    MultipartHttpServletRequest resolveMultipart(HttpServletRequest var1) throws MultipartException;
  
    //
    void cleanupMultipart(MultipartHttpServletRequest var1);
}

我們知道,相應的請求會被DispatchServlet的doDispatch方法攔截,doDispatch方法中共首先就會調用checkMultipart方法檢查請求是否是包含文件流:

protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {
        if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) {
            if (WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class) != null) {
                this.logger.debug("...");
            } else if (this.hasMultipartException(request)) {
                this.logger.debug("...");
            } else {
                try {
                    // 具體的文件流解析方法
                    return this.multipartResolver.resolveMultipart(request);
                    ...
}  

配置例子

CommonsFileUploadSupport實現了 MultipartResolver 接口

//上傳文件配置
@Bean(name = "multipartResolver")
public CommonsFileUploadSupport commonsFileUploadSupport(){
    CommonsFileUploadSupport resolver = new CommonsMultipartResolver();
    resolver.setMaxInMemorySize(40960);
    resolver.setMaxUploadSize(10485760000L);
    return resolver;
}

  

 

2. initLocaleResolver 國際化

DispatcherServlet.properties文件:

org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver

org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver

org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
	org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping

org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
	org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
	org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter

org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,\
	org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
	org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver

org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator

org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver

org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager

DispatchServlet中定義一個靜態的容器初始化默認defaultStrategies方法塊,如果用戶沒有自定義的話,就使用默認的,

static {
    // Load default strategy implementations from properties file.
    // This is currently strictly internal and not meant to be customized
    // by application developers.
    try {
        ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);
        defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
    }
    catch (IOException ex) {
        throw new IllegalStateException("Could not load '" +     DEFAULT_STRATEGIES_PATH + "': " + ex.getMessage());
    }
}

流程:

1. this.localeResolver = getDefaultStrategy(context, LocaleResolver.class);
 
2. List<T> strategies = getDefaultStrategies(context, strategyInterface)

3. String key = strategyInterface.getName();
   String value = defaultStrategies.getProperty(key);
   // 如果value不為空, 將value轉換為class類名稱,然后在容器了創建對象
   Object strategy = this.createDefaultStrategy(context, clazz);

pringMVC國際化提供了四個國際化的實現的類AcceptHeaderLocaleResolver(默認),FixedLocaleResolver、CookieLocaleResolver和SessionLocaleResolver。

 

 

3. initThemeResolver 主題

主題的實現原理:大概就是把網站版面的css樣式表和圖片之類的文件和網站的程序進行解耦,程序讀取theme的持久化配置,然后找到相應的css樣式表和圖片,配置網站版面。

要在程序中使用主題,必須設置一個org.springframework.ui.context.ThemeSource的實現類。SpringMVC IOC容器本身實現了ThemeSource,這個類只是簡單的把責任代理給了一個特定的實現類,默認情況下這個代理類是:org.springframework.ui.context.support.ResourceBundleThemeSource,這個實現類可以從classpath目錄下載入一個properties文件。如設置setBasenamePrefix、setDefaultEncoding等。

原理(實踐)

如:SpringMVC中一套主題對應一個cool.properties文件,該文件在classpath根目錄下, 這個文件列出了主題組成的資源:

styleSheet=/themes/cool/style.css
background=/themes/cool/img/coolBg.jpg

properties文件中的key是指視圖文件中元素的名稱,value值主題存放的位置。jsp中可以通過jsp文件可以通過spring:theme來訪問這個key,然后找到value(對應的主題)。

ResourceBundleThemeSourceuses(默認的ThemeSource)的作用是根據主題名找到具體的主題,這個例子中就是找到配置文件themedemo.properties中的,默認情況下ResourceBundleThemeSource使用空的前綴名稱,所以,classpath根目錄下的properties文件會被載入。如果想制定位置,則可以使用basenamePrefix

找到主題文件后,如何去解析?此時就出現了ThemeResolver。

SpringMVC中有實現主題類有3個:

  1. FixedThemeResolver(默認):固定格式的theme,不能在系統運行時動態更改theme。

  2. SessionThemeResolver:可在運行中通過更改cookie中的相應的key值來動態調整theme的值。

  3. CookieThemeResolver:可在運行中通過更改session中的相應的key值來動態調整theme的值

主題加載策略和initLocaleResolver類似,也是如果用戶沒有自定義就采用默認的方式。默認的方式為FixedThemeResolver。

一個例子:

application context .xml配置文件:

<bean class="org.springframework.ui.context.support.ResourceBundleThemeSource" id="themeSource">  
    <property name="basenamePrefix" value="themes/"></property>  
</bean>  
<bean id="themeResolver"  class="org.springframework.web.servlet.theme.SessionThemeResolver">  
    <property name="defaultThemeName" value="red" />  
</bean>

簡單敘述為:ThemeResolver找到themes/目錄下的所有properties中,然后SessionThemeResolver在發生改變主題請求后來解析主題。

附:如果需要根據用戶請求來改變主題,則需要使用ThemeChangeInterceptor攔截器來改變主題。(攔截器有關的知識可以看本文下面的handlerMapping)

參考:

https://www.xuebuyuan.com/zh-tw/1578077.html

https://blog.csdn.net/u012410733/article/details/52915063

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM