Spring之SpringMVC(源码)初始化DispatcherServlet策略配置
1.从上一篇文章中可以SpringMVC初始化的过程中完成的其中一件事就是DispatcherServlet的相关策略的配置,如下所示
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
}
下面分别看下,每个策略配置的具体实现
2.文件类型解析器
private void initMultipartResolver(ApplicationContext context) {
try {
//public static final String MULTIPART_RESOLVER_BEAN_NAME = "multipartResolver"
this.multipartResolver = context.getBean(MULTIPART_RESOLVER_BEAN_NAME, MultipartResolver.class);
if (logger.isDebugEnabled()) {
logger.debug("Using MultipartResolver [" + this.multipartResolver + "]");
}
}
catch (NoSuchBeanDefinitionException ex) {
// Default is no multipart resolver.
this.multipartResolver = null;
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate MultipartResolver with name '" + MULTIPART_RESOLVER_BEAN_NAME +
"': no multipart request handling provided");
}
}
}
通过初始化这个类来处理文件解析,但是也可以发现如果没有提供的话,就会给出一个空的的解析器。
3. LocaleResolver解析器
private void initLocaleResolver(ApplicationContext context) {
try {// public static final String LOCALE_RESOLVER_BEAN_NAME = "localeResolver";
this.localeResolver = context.getBean(LOCALE_RESOLVER_BEAN_NAME, LocaleResolver.class);
if (logger.isDebugEnabled()) {
logger.debug("Using LocaleResolver [" + this.localeResolver + "]");
}
}
catch (NoSuchBeanDefinitionException ex) {
// We need to use the default.
this.localeResolver = getDefaultStrategy(context, LocaleResolver.class);
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate LocaleResolver with name '" + LOCALE_RESOLVER_BEAN_NAME +
"': using default [" + this.localeResolver + "]");
}
}
}
为了让web应用程序支持国际化,必须识别每个用户的首选区域,并根据这个区域显示内容。LocaleResolver解析器主要解决国际化的问题。如果配置了那么就使用所配置的解析器,如果没有配置的话,那么就是用默认提供的AcceptHeaderLocaleResolver。
4.ThemeResolver
主题样式解析器,
private void initThemeResolver(ApplicationContext context) {
try {// public static final String THEME_RESOLVER_BEAN_NAME = "themeResolver";
this.themeResolver = context.getBean(THEME_RESOLVER_BEAN_NAME, ThemeResolver.class);
if (logger.isDebugEnabled()) {
logger.debug("Using ThemeResolver [" + this.themeResolver + "]");
}
}
catch (NoSuchBeanDefinitionException ex) {
// We need to use the default.
this.themeResolver = getDefaultStrategy(context, ThemeResolver.class);
if (logger.isDebugEnabled()) {
logger.debug(
"Unable to locate ThemeResolver with name '" + THEME_RESOLVER_BEAN_NAME + "': using default [" +
this.themeResolver + "]");
}
}
}
如果提供了提供了相应的主题解析器,那么就是用,否则的话就是提供一个默认的FixedThemeResolver来作为主题解析器,
5.处理器映射解析器
private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null; if (this.detectAllHandlerMappings) {
// Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
Map<String, HandlerMapping> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerMappings = new ArrayList<HandlerMapping>(matchingBeans.values());
// We keep HandlerMappings in sorted order.
OrderComparator.sort(this.handlerMappings);
}
}
else {
try {
HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
this.handlerMappings = Collections.singletonList(hm);
}
catch (NoSuchBeanDefinitionException ex) {
// Ignore, we'll add a default HandlerMapping later.
}
}
请求到处理器的映射,如果映射成功返回一个HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个HandlerInterceptor拦截器)对象;BeanNameUrlHandlerMapping将URL与Bean名字映射,映射成功的Bean就是此处的处理器;通过这个类来初始化HandlerMappings,主要完成请求和处理器之间的映射关系。如果没有提供的话那么就会使用默认的BeanNameUrlHandlerMapping来进项相关的处理。我们来看下大致的处理过程。首先会获取所有的处理映射,然后对这些请求映射进项排序;如果请求映射集合为空,那么就会找到系统中的HandlerMapping,并且进行单例操作处理。如果这个HandlerMapping对象为空,就会使用默认的HandlerMapping,也就是BeanNameUrlHandlerMapping。
6.handlerAdapter解析器
private void initHandlerAdapters(ApplicationContext context) {
this.handlerAdapters = null; if (this.detectAllHandlerAdapters) {
// Find all HandlerAdapters in the ApplicationContext, including ancestor contexts.
Map<String, HandlerAdapter> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerAdapters = new ArrayList<HandlerAdapter>(matchingBeans.values());
// We keep HandlerAdapters in sorted order.
OrderComparator.sort(this.handlerAdapters);
}
}
else {
try {
HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);
this.handlerAdapters = Collections.singletonList(ha);
}
catch (NoSuchBeanDefinitionException ex) {
// Ignore, we'll add a default HandlerAdapter later.
}
} // Ensure we have at least some HandlerAdapters, by registering
// default HandlerAdapters if no other adapters are found.
if (this.handlerAdapters == null) {
this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
if (logger.isDebugEnabled()) {
logger.debug("No HandlerAdapters found in servlet '" + getServletName() + "': using default");
}
}
}
HandlerAdapter将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器。也就是说按照特定规则(HandlerAdapter要求的规则)去执行Handler。它会首先获取ApplicationContext中所有的处理适配器,如果获取集合不为空,需要进行排序处理。没有找到,则会查找系统中的handlerAdapter,然后进行单例化处理。如果查找的系统handlerAdapter为空,则使用默认的适配器,也即是SimpleControllerHandlerAdapter,它将对实现了Controller接口的Bean进行适配,并且掉处理器的handleRequest方法进行功能处理。
7.HandlerExceptionResolver
private void initHandlerExceptionResolvers(ApplicationContext context) {
this.handlerExceptionResolvers = null; if (this.detectAllHandlerExceptionResolvers) {
// Find all HandlerExceptionResolvers in the ApplicationContext, including ancestor contexts.
Map<String, HandlerExceptionResolver> matchingBeans = BeanFactoryUtils
.beansOfTypeIncludingAncestors(context, HandlerExceptionResolver.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerExceptionResolvers = new ArrayList<HandlerExceptionResolver>(matchingBeans.values());
// We keep HandlerExceptionResolvers in sorted order.
OrderComparator.sort(this.handlerExceptionResolvers);
}
}
else {
try {
HandlerExceptionResolver her =
context.getBean(HANDLER_EXCEPTION_RESOLVER_BEAN_NAME, HandlerExceptionResolver.class);
this.handlerExceptionResolvers = Collections.singletonList(her);
}
catch (NoSuchBeanDefinitionException ex) {
// Ignore, no HandlerExceptionResolver is fine too.
}
} // Ensure we have at least some HandlerExceptionResolvers, by registering
// default HandlerExceptionResolvers if no other resolvers are found.
if (this.handlerExceptionResolvers == null) {
this.handlerExceptionResolvers = getDefaultStrategies(context, HandlerExceptionResolver.class);
if (logger.isDebugEnabled()) {
logger.debug("No HandlerExceptionResolvers found in servlet '" + getServletName() + "': using default");
}
}
}
通过这个方法来初始化HandlerExceptionResolver,如果没有配置,系统默认不会提供处理器异常解析器,会给一个空的来作为默认。它首先会查找ApplicationContext中所有的配置的处理器异常解析器,包括它的父容器的范围的,如果找到了会进行有序处理操作( Map<String, HandlerExceptionResolver>);如果找不到具体的映射配置,那么就会获取ApplicationContext中的HandlerExceptionResolver并且进行单例化处理。如果获取的这个解析器为空,那么就会使用默认的,也就是空的解析器处理。
8.RequestToViewNameTranslator
private void initRequestToViewNameTranslator(ApplicationContext context) {
try {
this.viewNameTranslator =
context.getBean(REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME, RequestToViewNameTranslator.class);
if (logger.isDebugEnabled()) {
logger.debug("Using RequestToViewNameTranslator [" + this.viewNameTranslator + "]");
}
}
catch (NoSuchBeanDefinitionException ex) {
// We need to use the default.
this.viewNameTranslator = getDefaultStrategy(context, RequestToViewNameTranslator.class);
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate RequestToViewNameTranslator with name '" +
REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME + "': using default [" + this.viewNameTranslator +
"]");
}
}
}
通过提供的 Servlet实例来初始化RequestToViewNameTranslator,如果没有提供的话,就会使用系统默认的DefaultRequestToViewNameTranslator。
9.视图解析器
private void initViewResolvers(ApplicationContext context) {
this.viewResolvers = null; if (this.detectAllViewResolvers) {
// Find all ViewResolvers in the ApplicationContext, including ancestor contexts.
Map<String, ViewResolver> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, ViewResolver.class, true, false);
if (!matchingBeans.isEmpty()) {
this.viewResolvers = new ArrayList<ViewResolver>(matchingBeans.values());
// We keep ViewResolvers in sorted order.
OrderComparator.sort(this.viewResolvers);
}
}
else {
try {
ViewResolver vr = context.getBean(VIEW_RESOLVER_BEAN_NAME, ViewResolver.class);
this.viewResolvers = Collections.singletonList(vr);
}
catch (NoSuchBeanDefinitionException ex) {
// Ignore, we'll add a default ViewResolver later.
}
} // Ensure we have at least one ViewResolver, by registering
// a default ViewResolver if no other resolvers are found.
if (this.viewResolvers == null) {
this.viewResolvers = getDefaultStrategies(context, ViewResolver.class);
if (logger.isDebugEnabled()) {
logger.debug("No ViewResolvers found in servlet '" + getServletName() + "': using default");
}
}
}
通过这个来进行视图解析器的初始化工作,如果没有提供的话那么就会使用InternalResourceViewResolver来进行处理,是不是对JSP页面处理的时候经常看到这个配置。
10.FlashMapManager
private void initFlashMapManager(ApplicationContext context) {
try {
this.flashMapManager =
context.getBean(FLASH_MAP_MANAGER_BEAN_NAME, FlashMapManager.class);
if (logger.isDebugEnabled()) {
logger.debug("Using FlashMapManager [" + this.flashMapManager + "]");
}
}
catch (NoSuchBeanDefinitionException ex) {
// We need to use the default.
this.flashMapManager = getDefaultStrategy(context, FlashMapManager.class);
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate FlashMapManager with name '" +
FLASH_MAP_MANAGER_BEAN_NAME + "': using default [" + this.flashMapManager + "]");
}
}
}
从方法中的注释可知,如果用户没有提供它的配置,那么就是使用spring提供的org.springframework.web.servlet.support.DefaultFlashMapManager来作为默认的处理。
11.常量配置
11.1关于上面的初始化的配置常量
/** Well-known name for the MultipartResolver object in the bean factory for this namespace. */
public static final String MULTIPART_RESOLVER_BEAN_NAME = "multipartResolver"; /** Well-known name for the LocaleResolver object in the bean factory for this namespace. */
public static final String LOCALE_RESOLVER_BEAN_NAME = "localeResolver"; /** Well-known name for the ThemeResolver object in the bean factory for this namespace. */
public static final String THEME_RESOLVER_BEAN_NAME = "themeResolver"; /**
* Well-known name for the HandlerMapping object in the bean factory for this namespace.
* Only used when "detectAllHandlerMappings" is turned off.
* @see #setDetectAllHandlerMappings
*/
public static final String HANDLER_MAPPING_BEAN_NAME = "handlerMapping"; /**
* Well-known name for the HandlerAdapter object in the bean factory for this namespace.
* Only used when "detectAllHandlerAdapters" is turned off.
* @see #setDetectAllHandlerAdapters
*/
public static final String HANDLER_ADAPTER_BEAN_NAME = "handlerAdapter"; /**
* Well-known name for the HandlerExceptionResolver object in the bean factory for this namespace.
* Only used when "detectAllHandlerExceptionResolvers" is turned off.
* @see #setDetectAllHandlerExceptionResolvers
*/
public static final String HANDLER_EXCEPTION_RESOLVER_BEAN_NAME = "handlerExceptionResolver"; /**
* Well-known name for the RequestToViewNameTranslator object in the bean factory for this namespace.
*/
public static final String REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME = "viewNameTranslator"; /**
* Well-known name for the ViewResolver object in the bean factory for this namespace.
* Only used when "detectAllViewResolvers" is turned off.
* @see #setDetectAllViewResolvers
*/
public static final String VIEW_RESOLVER_BEAN_NAME = "viewResolver"; /**
* Well-known name for the FlashMapManager object in the bean factory for this namespace.
*/
public static final String FLASH_MAP_MANAGER_BEAN_NAME = "flashMapManager"; /**
* Request attribute to hold the current web application context.
* Otherwise only the global web app context is obtainable by tags etc.
* @see org.springframework.web.servlet.support.RequestContextUtils#getWebApplicationContext
*/
public static final String WEB_APPLICATION_CONTEXT_ATTRIBUTE = DispatcherServlet.class.getName() + ".CONTEXT"; /**
* Request attribute to hold the current LocaleResolver, retrievable by views.
* @see org.springframework.web.servlet.support.RequestContextUtils#getLocaleResolver
*/
public static final String LOCALE_RESOLVER_ATTRIBUTE = DispatcherServlet.class.getName() + ".LOCALE_RESOLVER"; /**
* Request attribute to hold the current ThemeResolver, retrievable by views.
* @see org.springframework.web.servlet.support.RequestContextUtils#getThemeResolver
*/
public static final String THEME_RESOLVER_ATTRIBUTE = DispatcherServlet.class.getName() + ".THEME_RESOLVER"; /**
* Request attribute to hold the current ThemeSource, retrievable by views.
* @see org.springframework.web.servlet.support.RequestContextUtils#getThemeSource
*/
public static final String THEME_SOURCE_ATTRIBUTE = DispatcherServlet.class.getName() + ".THEME_SOURCE"; /**
* Name of request attribute that holds a read-only {@code Map<String,?>}
* with "input" flash attributes saved by a previous request, if any.
* @see org.springframework.web.servlet.support.RequestContextUtils#getInputFlashMap(HttpServletRequest)
*/
public static final String INPUT_FLASH_MAP_ATTRIBUTE = DispatcherServlet.class.getName() + ".INPUT_FLASH_MAP"; /**
* Name of request attribute that holds the "output" {@link FlashMap} with
* attributes to save for a subsequent request.
* @see org.springframework.web.servlet.support.RequestContextUtils#getOutputFlashMap(HttpServletRequest)
*/
public static final String OUTPUT_FLASH_MAP_ATTRIBUTE = DispatcherServlet.class.getName() + ".OUTPUT_FLASH_MAP"; /**
* Name of request attribute that holds the {@link FlashMapManager}.
* @see org.springframework.web.servlet.support.RequestContextUtils#getFlashMapManager(HttpServletRequest)
*/
public static final String FLASH_MAP_MANAGER_ATTRIBUTE = DispatcherServlet.class.getName() + ".FLASH_MAP_MANAGER"; /** Log category to use when no mapped handler is found for a request. */
public static final String PAGE_NOT_FOUND_LOG_CATEGORY = "org.springframework.web.servlet.PageNotFound"; /**
* Name of the class path resource (relative to the DispatcherServlet class)
* that defines DispatcherServlet's default strategy names.
*/
private static final String DEFAULT_STRATEGIES_PATH = "DispatcherServlet.properties";
11.2Spring提供的默认配置文件DispatcherServlet.properties
# Default implementation classes for DispatcherServlet's strategy interfaces.
# Used as fallback when no matching beans are found in the DispatcherServlet context.
# Not meant to be customized by application developers. 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
有上面的SpringMVC默认的配置文件可知,相应的策略实现有系统默认的配置项。
Spring之SpringMVC(源码)初始化DispatcherServlet策略配置的更多相关文章
- MyBatis、Spring、SpringMVC 源码下载地址
MyBatis.Spring.SpringMVC 源码下载地址 github mybatis https://github.com/fengyu415/MyBatis-Learn.git spring ...
- springMVC源码分析--DispatcherServlet请求获取及处理
在之前的博客springMVC源码分析--容器初始化(二)DispatcherServlet中我们介绍过DispatcherServlet,是在容器初始化过程中出现的,我们之前也说过Dispatche ...
- Java工程师学习指南第3部分:Spring与SpringMVC源码解析
本文整理了微信公众号[Java技术江湖]发表和转载过的Spring全家桶优质文章,想看到更多Java技术文章,就赶紧关注吧. 前后端分离,我怎么就选择了 Spring Boot + Vue 技术栈? ...
- SpringMVC源码解析-DispatcherServlet启动流程和初始化
在使用springmvc框架,会在web.xml文件配置一个DispatcherServlet,这正是web容器开始初始化,同时会在建立自己的上下文来持有SpringMVC的bean对象. 先从Dis ...
- Spring之SpringMVC(源码)启动初始化过程分析
1.说明 SpringMVC作为Spring提供的MVC实现,可以实现与Spring的天然无缝联合,因为具有很广泛的用途.具体的关于SpringMVC的处理流程逻辑我在这里就不在赘述了.还是来通过源码 ...
- SpringMVC源码分析--容器初始化(五)DispatcherServlet
上一篇博客SpringMVC源码分析--容器初始化(四)FrameworkServlet我们已经了解到了SpringMVC容器的初始化,SpringMVC对容器初始化后会进行一系列的其他属性的初始化操 ...
- springMVC源码分析--容器初始化(二)DispatcherServlet
在上一篇博客springMVC源码分析--容器初始化(一)中我们介绍了spring web初始化IOC容器的过程,springMVC作为spring项目中的子项目,其可以和spring web容器很好 ...
- SpringMVC源码情操陶冶-DispatcherServlet类简析(一)
阅读源码有利于陶冶情操,此文承接前文SpringMVC源码情操陶冶-DispatcherServlet父类简析 注意:springmvc初始化其他内容,其对应的配置文件已被加载至beanFactory ...
- SpringMVC源码剖析(四)- DispatcherServlet请求转发的实现
SpringMVC完成初始化流程之后,就进入Servlet标准生命周期的第二个阶段,即“service”阶段.在“service”阶段中,每一次Http请求到来,容器都会启动一个请求线程,通过serv ...
随机推荐
- Nginx搭建反向代理服务器过程详解(转)
一.反向代理 我们都知道,80端口是web服务的默认端口,其他主机访问web服务器也是默认和80端口进行web交互,而一台服务器也只有一个80端口,这是约定俗成的标准. 我们来看下面两个场景: 1.服 ...
- 面向对象的软件project——面向对象分析
为了解决软件危机.一些IT前辈国产软件project这个词汇,软件project它被引入到整个软件开发过程的维护. 软件project从程序的设计角度能够分为两类.一类是面向结构的软件project. ...
- Android有关JNI 学习(两)为JNI方法名称,数据类型和方法签名的一些知识
我们知道,使用javah产生c/c++当在头文件,将java定义 native 功能,以产生相应jni层功能,如下面: /* * Class: com_lms_jni_JniTest * Method ...
- 解决win10客户机本地账户登陆导致远程桌面没法访问问题
情景:客户机器如果是win10本地账户,我们远程桌面连接是可能会没法访问. 如果客户机器切换到win10 Microsoft账户登录,远程桌面就可以访问了(当然用户肯定不能给你说自己的Microsof ...
- 远程访问mysql(转)
GRANT ALL PRIVILEGES ON *.* TO '<username>'@'<remote addr or %(for all ip addr)>'IDENTIF ...
- [Unity3D]Unity3D圣骑士当游戏开发商遭遇Mecanim动画系统
大家好.我是秦培.欢迎关注我的博客.我的博客地址blog.csdn.net/qinyuanpei. 博主总算赶在这个月底写出了这篇文章.这个月由于期末考试一直没时间研究太多关于技术方面 ...
- Oracle 实现 mysql 的 find_in_set 排序!
oracle 实现类似MYSQL的 find_in_set 排序,函数 decode: select * from tb_info_game where gameid in(23,20,19,26,1 ...
- nefu117 素数个数的位数,素数定理
素数个数的位数 Time Limit 1000ms Memory Limit 65536K description 小明是一个聪明的孩子,对数论有着非常浓烈的兴趣.他发现求1到正整数10n 之间有多少 ...
- 【日报C在23】堆和栈的深入了解
每日一C之堆与栈的深入理解 每天拾一个C语言贝壳,厚积薄发,积跬步以致千里. 今日贝壳:内存中堆与栈的深入理解.认识一个清晰地内存 假 ...
- QtQuick桌面应用程序开发指导 3)达到UI而功能_B 4)动态管理Note物_A
3.2 把Page Item和Marker Item绑定 之前我们实现了PagePanel组件, 使用了三个state来切换Page组件的opacity属性; 这一步我们会使用Marker和Marke ...