SpringMVC源码分析--容器初始化(五)DispatcherServlet
上一篇博客SpringMVC源码分析--容器初始化(四)FrameworkServlet我们已经了解到了SpringMVC容器的初始化,SpringMVC对容器初始化后会进行一系列的其他属性的初始化操作,在SpringMVC初始化完成之后会调用onRefresh(wac)方法,它通过模板方式在子类DispatcherServlet中实现的。
onRefresh函数实现如下,其具体的实现就放到initStrategies函数中实现。
/** * This implementation calls {@link #initStrategies}. */ //初始化策略,完成SpringMVC默认实现类的初始化,onRefresh是在父类FrameworkServlet中调用 @Override protected void onRefresh(ApplicationContext context) { initStrategies(context); }
initStrategies函数中初始化了一些springMVC运行过程中需要使用的默认的实现类,接下来我们分别介绍一下默认实现的 类。
//初始化SpringMVC的一些策略,也是springMVC主要的组件 protected void initStrategies(ApplicationContext context) { initMultipartResolver(context);//文件上传解析,如果请求类型是multipart将通过MultipartResolver进行文件上传解析 initLocaleResolver(context);//本地化解析 initThemeResolver(context);//主题解析 initHandlerMappings(context);//通过HandlerMapping,将请求映射到处理器 initHandlerAdapters(context);//通过HandlerAdapter支持多种类型的处理器 initHandlerExceptionResolvers(context);//如果执行过程中遇到异常,将交给HandlerExceptionResolver来解析 initRequestToViewNameTranslator(context);//直接解析请求到视图名 initViewResolvers(context);//通过viewResolver解析逻辑视图到具体视图实现 initFlashMapManager(context);//flash映射管理器 }
initMultipartResolver初始化文件上传解析器,与文件上传的相关的操作,有关文件上传操作我们会仔细分析,这里不做过多介绍。
////文件上传解析,如果请求类型是multipart将通过MultipartResolver进行文件上传解析 private void initMultipartResolver(ApplicationContext context) { try { //bean id被写死,在配置的时候需要注意,文件上传时需要注入bean名称为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"); } } }
initLocaleResolver是初始化一些多语言实现相关的类,在配置多语言本地化时会注入bean名称为localeResolver,默认实现的类有FixedLocaleResolver ,SessionLocaleResolver ,CookieLocaleResolver, AcceptHeaderLocaleResolver
//本地化解析,支持web应用程序国际化,在springMVC应用程序中,用户的区域是通过区域解析器事变的 //spring采用的是默认区域解析器 AcceptHeaderLocaleResolver ,通过检验HTTP请求的accept-language头部来解析区域 //这个头部是有用户的浏览器根据底层操作系统的区域设置进行设定,这个区域解析器无法改变用户的区域,因为无法修改用户 //操作系统的区域设置 private void initLocaleResolver(ApplicationContext context) { try { //在配置多语言本地化时会注入bean名称为localeResolver,默认实现的类有FixedLocaleResolver ,SessionLocaleResolver ,CookieLocaleResolver, AcceptHeaderLocaleResolver 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 + "]"); } } }
initThemeResolver与样式相关的解析器,需要在配置文件中注入bean名称为themeResolver的,FixedThemeResolver, SessionThemeResolver和CookieThemeResolver
//动态样式支持 private void initThemeResolver(ApplicationContext context) { try { //需要在配置文件中注入bean名称为themeResolver的,FixedThemeResolver, SessionThemeResolver和CookieThemeResolver 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 + "]"); } } }
initHandlerMappings初始化HandlerMapping,HandlerMapping的工作就是为每个请求找到合适的请求找到一个处理器handler
//会加载HandlerMapping,默认使用BeanNameUrlHandlerMapping private void initHandlerMappings(ApplicationContext context) { this.handlerMappings = null; if (this.detectAllHandlerMappings) { // Find all HandlerMappings in the ApplicationContext, including ancestor contexts. //默认加载所有的HandlerMapping, Map<String, HandlerMapping> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false); if (!matchingBeans.isEmpty()) { //数组中含有多个HandlerMapping this.handlerMappings = new ArrayList<HandlerMapping>(matchingBeans.values()); // We keep HandlerMappings in sorted order. AnnotationAwareOrderComparator.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. } } // Ensure we have at least one HandlerMapping, by registering // a default HandlerMapping if no other mappings are found. if (this.handlerMappings == null) { this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class); if (logger.isDebugEnabled()) { logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default"); } } }
initHandlerAdapters是初始化HandlerAdapter,HandlerAdapter是真正调用Controller操作的类
//初始化HandlerAdapters,默认使用的是SimpleControllerHandlerAdapter 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()) { //数组中含有多个HandlerAdapters this.handlerAdapters = new ArrayList<HandlerAdapter>(matchingBeans.values()); // We keep HandlerAdapters in sorted order. AnnotationAwareOrderComparator.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. } } //如果没有设置HandlerAdapters,则获取默认的配置 if (this.handlerAdapters == null) { this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class); if (logger.isDebugEnabled()) { logger.debug("No HandlerAdapters found in servlet '" + getServletName() + "': using default"); } } }
initHandlerExceptionResolvers是初始化HandlerExceptionResolver,用来操作异常,接下来我们会对其进行详细分析
//初始化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. AnnotationAwareOrderComparator.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"); } } }
initRequestToViewNameTranslator是初始化到ViewName的处理器。
/* 返回一个对应的视图名称*/ 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 + "]"); } } }
initViewResolvers初始化View的解析器
//初始化viewResolver 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. AnnotationAwareOrderComparator.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"); } } }
initFlashMapManager初始化FlashMapManager,与链接跳转相关的。
//初始化 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 + "]"); } } }
这样就完成了SpringMVC工程启动时初始化的所有工作了,主要就是完成IOC容器的初始化和一些默认实现的初始化,这样就完成了SpringMVC的初始化工作,接下来就是对Controller的访问链接的处理,我们会一步一步的写源码博客进行分析的。
SpringMVC源码分析--容器初始化(五)DispatcherServlet的更多相关文章
- springMVC源码分析--容器初始化(二)DispatcherServlet
在上一篇博客springMVC源码分析--容器初始化(一)中我们介绍了spring web初始化IOC容器的过程,springMVC作为spring项目中的子项目,其可以和spring web容器很好 ...
- SpringMVC源码分析--容器初始化(四)FrameworkServlet
在上一篇博客SpringMVC源码分析--容器初始化(三)HttpServletBean我们介绍了HttpServletBean的init函数,其主要作用是初始化了一下SpringMVC配置文件的地址 ...
- SpringMVC源码分析--容器初始化(三)HttpServletBean
在上一篇博客springMVC源码分析--容器初始化(二)DispatcherServlet中,我们队SpringMVC整体生命周期有一个简单的说明,并没有进行详细的源码分析,接下来我们会根据博客中提 ...
- springMVC源码分析--容器初始化(一)ContextLoaderListener
在spring Web中,需要初始化IOC容器,用于存放我们注入的各种对象.当tomcat启动时首先会初始化一个web对应的IOC容器,用于初始化和注入各种我们在web运行过程中需要的对象.当tomc ...
- SpringMVC源码分析(3)DispatcherServlet的请求处理流程
<springmvc源码分析(2)dispatcherservlet的初始化>初始化DispatcherServlet的多个组件. 本文继续分析DispatcherServlet解析请求的 ...
- springMVC源码分析--AbstractDetectingUrlHandlerMapping(五)
上一篇博客springMVC源码分析--AbstractUrlHandlerMapping(三)中我们介绍了AbstractUrlHandlerMapping,主要介绍了一个handlerMap的ur ...
- springMVC源码分析--RequestMappingHandlerAdapter(五)
上一篇博客springMVC源码分析--HandlerAdapter(一)中我们主要介绍了一下HandlerAdapter接口相关的内容,实现类及其在DispatcherServlet中执行的顺序,接 ...
- springMVC源码分析--DispatcherServlet请求获取及处理
在之前的博客springMVC源码分析--容器初始化(二)DispatcherServlet中我们介绍过DispatcherServlet,是在容器初始化过程中出现的,我们之前也说过Dispatche ...
- springMVC源码分析--AbstractControllerUrlHandlerMapping(六)
上一篇博客springMVC源码分析--AbstractDetectingUrlHandlerMapping(五)中我们介绍了AbstractDetectingUrlHandlerMapping,其定 ...
随机推荐
- IDF实验室-CTF训练营-牛刀小试CTF
自从开始玩CTF后,发现这个游戏还是比较有意思,发现了一个练习场地IDF实验室:http://ctf.idf.cn/ 刷刷里面的题目,今天完成了其中的牛刀小试,分享一下解题思路: 1. 被改错的密码 ...
- spring 自定义事件发布及监听(简单实例)
前言: Spring的AppilcaitionContext能够发布事件和注册相对应的事件监听器,因此,它有一套完整的事件发布和监听机制. 流程分析: 在一个完整的事件体系中,除了事件和监听器以外,还 ...
- scanf———while(scanf ("%lu",&num) = =1)什么意思
scanf的返回值由后面的参数决定 scanf("%d%d", &a, &b); 如果a和b都被成功读入,那么scanf的返回值就是2 如果只有a被成功读入,返回值 ...
- audioplayer.js插件的使用及小bug
之前在项目里用audioplayer.js做的一个页面,改了布局样式,还有插件自身有个bug就是audio添加autoplay属性后有两个音频播放,其中一个无法控制,会一直播放,我查看了官网的demo ...
- html取地址栏参数的方法
现在的人写的博客真是日常挖坑 闲的蛋疼 想把所有东西都转成jstl格式 有个界面是取地址栏的信息的 之前用的是 <%--不用jstl的方法直接传递--%> <%--String ro ...
- 用js实现排列组合
在leetcode上看到一个题,代码实现排列组合的. 记得大学上课时候,就用c写过,现在用js试试,顺便看看耗时. 先看看3的阶乘: function permute(temArr,testArr){ ...
- 利用create-react-app结合react-redux、react-router4构建单页应用
1.创建项目: a.全局安装create-react-app: npm install create-react-app -g b.执行create-react-app my-projectN ...
- vue2.0+ 从插件开发到npm发布
vue: V2.5.11 此篇尽量详细,清楚的讲解vue插件的开发到npm的发布,想想将你自己做的东西展示给广大"网民",心里还是有点小激动的...-^_^ 先上一下插件效果图-- ...
- VMware在宿主上没有VMnet0、VMnet8,解决方法
一开始,坐着上机实验,一直搞不通为什么虚拟机上的客户机可以ping通自己的ip也可以ping通自己本身的ip,但是主机ping不通虚拟机的客户机,也ping不通虚拟机的网关. 尝试了各种问题,也追出了 ...
- init,initialize,initWithFrame,initWithCoder,awakeFromNib等区别
1.init 与initialize 对于iOS程序,创建几个类对象,就会调用几次init.下面分别重写 举例如下: 创建一个Person类,分别重写initialize和init方法 #import ...