標籤:ant accept hand tst set ext 容器 could not commons
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.AcceptHeaderLocaleResolverorg.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolverorg.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMappingorg.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapterorg.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolverorg.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslatororg.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolverorg.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.cssbackground=/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個:
-
FixedThemeResolver(預設):固定格式的theme,不能在系統運行時動態更改theme。
-
SessionThemeResolver:可在運行中通過更改cookie中的相應的key值來動態調整theme的值。
-
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
52915063
springmvc DispatchServlet初始化九大載入策略(一)