阅读源码有利于陶冶情操,此文承接前文SpringMVC源码情操陶冶-DispatcherServlet父类简析

注意:springmvc初始化其他内容,其对应的配置文件已被加载至beanFactory中

DispatcherServlet#静态方法

DispatcherServlet静态块读取DispatcherServlet.properties,其中包含默认的策略实现

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 'DispatcherServlet.properties': " + ex.getMessage());
}
}

简单看下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 #url映射
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

DispatcherServlet#onRefresh

复写父类FrameworkServlet的onRefresh()方法,springmvc以此来完善相应的初始化操作,代码如下

	//复写
@Override
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}

直接看DispatcherServlet#initStrategies()初始化springmvc的策略对象,代码如下

protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
}

以上述程序的执行顺序,逐个分析

DispatcherServlet#initMultipartResolver(ApplicationContext context)

根据官方注释,此会去加载beanFactory的multipartResolverbean对象,适用于处理文件上传的操作,简单代码如下

private void initMultipartResolver(ApplicationContext context) {
try {
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");
}
}
}

DispatcherServlet#initLocaleResolver(ApplicationContext context)

本地校对解析,官方解释为获取id="localeResolver"的bean对象,如果没有则使用默认的org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver类创建bean对象

private void initLocaleResolver(ApplicationContext context) {
try {
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 + "]");
}
}
}

Note:这里我们简单看下DispatcherServlet#getDefaultStrategy()的内部方法createDefaultStrategy()创建spring bean对象

protected Object createDefaultStrategy(ApplicationContext context, Class<?> clazz) {

//可通过ApplicationContext.getAutowireCapableBeanFactory()方法来额外的创建外部class为bean对象

return context.getAutowireCapableBeanFactory().createBean(clazz);

}

DispatcherServlet#initThemeResolver(ApplicationContext context)

DispatcherServlet#initLocaleResolver(ApplicationContext context),找寻id="themeResolver"的bean对象,没有则默认使用org.springframework.web.servlet.theme.FixedThemeResolver作为bean对象

DispatcherServlet#initHandlerMappings(ApplicationContext context)

初始化对资源访问的映射处理类,代码如下

private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null;
/***默认为true,表示从beanFactory和其父类获取所有的HandlerMapping
** beans
**<init-param>
* <param-name>detectAllHandlerMappings</param-name>
* <param-value>true/false</param-value>
*/
if (this.detectAllHandlerMappings) {
//从祖先类到子类都去找寻相应的资源
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 {
//否则获取本springmvc的上下文中的单个`id="handlerMapping"`的HandlerMapping bean
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.
}
} //如果detectAllHandlerMappings=false且springmvc不包含相应的`handlerMapping`bean 则取默认的HandlerMappings
if (this.handlerMappings == null) {
this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
if (logger.isDebugEnabled()) {
logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default");
}
}
}

默认的HandlerMappings为org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping

org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping,从字面上可知前者是根据beanName直接映射请求,后者是注解方式的映射请求

DispatcherServlet#initHandlerAdapters(ApplicationContext context)

此处类似DispatcherServlet#initHandlerMapping()

  1. detectAllHandlerAdapters默认为true,也可通过web.xml修改值,表示找寻所有满足HandlerAdapter.class的beans;若为false,则寻找springmvc本身上下文环境(springmvc配置文件)的id="handlerAdapter"的单个bean对象。所以不管如何,springmvc若指定了handlerAdapterbean,其总是会被加载

  2. 默认的策略对象为SimpleControllerHandlerAdapter-简单的Controller请求处理

DispatcherServlet#initHandlerExceptionResolvers(ApplicationContext context)

此处类似DispatcherServlet#initHandlerMapping()

  1. detectAllHandlerExceptionResolvers默认为true,也可通过web.xml修改值,表示找寻所有满足HandlerExceptionResolver.class的beans;若为false,则寻找springmvc本身上下文环境(springmvc配置文件)的id="handlerExceptionResolver"的单个bean对象。所以不管如何,springmvc若指定了handlerExceptionResolverbean,其总是会被加载

  2. 默认的策略对象为SimpleControllerHandlerAdapter-简单的Controller请求处理

DispatcherServlet#initRequestToViewNameTranslator(ApplicationContext context)

此处同DispatcherServlet#initLocaleResolver()方法

  1. 首先找寻springmvc上下文中的id="viewNameTranslator"的bean,类型为RequestToViewNameTranslator.class
  2. 不然则采用默认的策略对象org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator-对请求的URI直接映射到view对象

DispatcherServlet#initViewResolvers(ApplicationContext context)

此处类似DispatcherServlet#initViewResolvers()

  1. detectAllViewResolvers默认为true,也可通过web.xml修改值,表示找寻所有满足ViewResolver.class的beans;若为false,则寻找springmvc本身上下文环境(springmvc配置文件)的id="viewResolver"的单个bean对象。所以不管如何,springmvc若指定了viewResolverbean,其总是会被加载

  2. 默认的策略对象为InternalResourceViewResolver-默认解析为jsp视图

DispatcherServlet#initFlashMapManager(ApplicationContext context)

此处同DispatcherServlet#initLocaleResolver()方法

  1. 首先找寻springmvc上下文中的id="flashMapManager"的bean,类型为FlashMapManager.class
  2. 不然则采用默认的策略对象org.springframework.web.servlet.support.SessionFlashMapManager-保存并检索FlashMap属性

小结

本文只介绍springmvc额外的初始化操作,包括文件上传处理类、请求映射处理类/适配器、异常处理类、视图解析类等等

SpringMVC源码情操陶冶-DispatcherServlet类简析(一)的更多相关文章

  1. SpringMVC源码情操陶冶-DispatcherServlet父类简析

    阅读源码有助于陶冶情操,本文对springmvc作个简单的向导 springmvc-web.xml配置 <servlet> <servlet-name>dispatch< ...

  2. SpringMVC源码情操陶冶-HandlerAdapter适配器简析

    springmvc中对业务的具体处理是通过HandlerAdapter适配器操作的 HandlerAdapter接口方法 列表如下 /** * Given a handler instance, re ...

  3. SpringMVC源码情操陶冶-DispatcherServlet简析(二)

    承接前文SpringMVC源码情操陶冶-DispatcherServlet类简析(一),主要讲述初始化的操作,本文将简单介绍springmvc如何处理请求 DispatcherServlet#doDi ...

  4. SpringMVC源码情操陶冶-DispatcherServlet

    本文对springmvc核心类DispatcherServlet作下简单的向导,方便博主与读者查阅 DispatcherServlet-继承关系 分析DispatcherServlet的继承关系以及主 ...

  5. SpringMVC源码情操陶冶-RequestMappingHandlerAdapter适配器

    承接前文SpringMVC源码情操陶冶-HandlerAdapter适配器简析.RequestMappingHandlerAdapter适配器组件是专门处理RequestMappingHandlerM ...

  6. SpringMVC源码情操陶冶-FreeMarker之web配置

    前言:本文不讲解FreeMarkerView视图的相关配置,其配置基本由FreeMarkerViewResolver实现,具体可参考>>>SpringMVC源码情操陶冶-ViewRe ...

  7. SpringMVC源码情操陶冶-AnnotationDrivenBeanDefinitionParser注解解析器

    mvc:annotation-driven节点的解析器,是springmvc的核心解析器 官方注释 Open Declaration org.springframework.web.servlet.c ...

  8. SpringMVC源码情操陶冶-AbstractHandlerMethodMapping

    承接前文SpringMVC源码情操陶冶-AbstractHandlerMapping,本文将介绍如何注册HandlerMethod对象作为handler 类结构瞧一瞧 public abstract ...

  9. SpringMVC源码情操陶冶-AbstractUrlHandlerMapping

    承接前文SpringMVC源码情操陶冶-AbstractHandlerMapping,前文主要讲解了如何获取handler处理对象,本文将针对beanName注册为handler对象作下解析 Abst ...

随机推荐

  1. JS数组中shift()和push(),unshift()和pop()操作方法使用

    Javascript为数组专门提供了push和pop()方法,以便实现类似栈的行为.来看下面的例子: var colors=new Array();       //创建一个数组 var count= ...

  2. qt中moc的作用

    Qt 将源代码交给标准 C++ 编译器,如 gcc 之前,需要事先将这些扩展的语法去除掉.完成这一操作的就是 moc. moc 全称是 Meta-Object Compiler,也就是"元对 ...

  3. 织梦dedecmsV5.7联动类型无法显示的处理方法

    最近织梦dedecms在新的功能中添加了一个联动类型这样的一个功能.所谓的联动类型,类似于一级目录下有二级目录,二级目录下又有三级目录,可以理解为数据结构中树形结构.级和级之间都是有着联系的.为了让大 ...

  4. php的底层原理

    PHP说简单,但是要精通也不是一件简单的事.我们除了会使用之外,还得知道它底层的工作原理. PHP是一种适用于web开发的动态语言.具体点说,就是一个用C语言实现包含大量组件的软件框架.更狭义点看,可 ...

  5. Swift2

    Swift 里的数组和字典虽然都是结构体(struct),但在参数传递过程中处理方式却不一样,默认 Array 是引用传递,Dictionary 是值传递.而在 Java 中,由于数组和 Map 都是 ...

  6. Guake!

    快捷键及其定制: [全局快捷键] F12:显示/隐藏Guake的程序界面. [局部快捷键] Ctrl+Shift+T:新建标签页: Ctrl+Shift+W:关闭标签页: Ctrl+Shift+C:复 ...

  7. struts学习总结

    -- struts2 是在struts1和webwork基础上发展的全新框架. -- struts2解决的问题: 原始的servlet中,每需要操作一个crud的操作就要创建一个servlet,虽然后 ...

  8. ceph rbd 封装api

    1.安装python,uwsgi,nginx环境 pip安装省略 yumgroupinstall"Developmenttools" yuminstallzlib-develbzi ...

  9. cpp - 编译过程

    预处理 E:\CppSpace\hello>g++ -o main.i -E main.cpp E:\CppSpace\hello>dir /p 驱动器 E 中的卷是 固盘-项目 卷的序列 ...

  10. cookie sessionStorage localStorage 之间的关系

    先说一个cookie 因为HTTP是无状态的 所以cookie诞生 用于保存会话信息 大小 4096b 一般在4095b以内 数量限制 20 -50 根据浏览器不同 操作的是一个字符串 可以设置参数 ...