前面几篇文章都是针对于SpringMVC中的具体组件进行源码分析的;本文主要用于补充记录一下关于SpringMVC中九大组件的学习。这个会牵扯出除以前的几篇HandlerMapping
以外的其余一些基础组件。css
以前简单的有介绍过DispatcherServlet
这个类的体系结构,此处就再也不赘述了。在DispatcherServlet
类中,其在mvc子容器进行初始化时就会完成对九大组件的初始化工做,具体哪九大组件后面会慢慢说到。先来看下在DispatcherServlet
中是经过哪些方法来完成初始化工做的,先贴一段代码:html
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);
}
复制代码
上面代码中的onRefresh
方法就是DispatcherServlet
的入口方法。在onRefresh
中又经过调用initStrategies
方法来将各个组件的初始化逻辑进行整合,我的理解其实就是策略套策略,在一个就是职责也明确。java
在initStrategies
方法中又经过调用组件各自的初始化方法来完成具体的初始化工做。从这个地方其实就能够清楚的看出SpringMVC中的9个组件名称了。下面就来捋一捋这九大组件的基本职责。bash
关于handlermapping在下面几篇文章中作过一些基本介绍,可是还不是很全,对于handlermapping的子类尚未分析完,这个会后期更新的。session
对于HandlerMapping
来讲,其做用就是根据request
找到相应的处理器Handler
和Intecepter
拦截器。具体细节参数上面第一篇文章。mvc
若是说HandlerMapping
是一支笔,那么HandlerAdapter
就是用笔的人。也就是说HandlerAdapter
就是使用处理器干活的人。为何呢?来看下代码:app
public interface HandlerAdapter {
boolean supports(Object var1);
ModelAndView handle(HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception;
long getLastModified(HttpServletRequest var1, Object var2);
}
复制代码
是否是一目了然了,在HandlerAdapter
接口中提供了handle
这样一个方法,参数中Object handler第三个参数其实就是一个处理器,那咱们就知道了,handle
方法就是使用handler
来处理逻辑的。处理以后返回一个ModelAndView
。jsp
这个是SpringMVC
中的异常处理组件,HandlerExceptionResolver
这个组件的做用就是根据异常设置ModelAndView
,而后再将处理结果交给render
方法进行渲染。固然render
也仅仅只是负责将ModelAndView
渲染成页面,ModelAndView
的具体来源它不关心。源码分析
这里须要说明一下,加入在渲染过程当中发生异常怎么办?从上面的分析咱们能够清楚的知道,HandlerExceptionResolver
这个组件对异常的处理结果是ModelAndView
,而后再由render
方法进行渲染,也就是说HandlerExceptionResolver
是在渲染以前工做的,所以渲染过程当中发生异常,HandlerExceptionResolver
是不会处理的。post
public interface HandlerExceptionResolver {
ModelAndView resolveException(HttpServletRequest var1, HttpServletResponse var2, Object var3, Exception var4);
}
复制代码
在HandlerExceptionResolver
中也只有一个方法,这个方法就是从异常中解析出ModelAndView
。
ViewResolver
的做用是将String
类型的逻辑视图根据local解析为View
视图的。下面是ViewResolver
的源码接口定义:
public interface ViewResolver {
View resolveViewName(String viewName, Locale local) throws Exception;
}
复制代码
从代码中能够看到,在ViewResolver
中也是只有一个方法,从resolveViewName
方法的参数和返回结果就很好的解释了其做用。
View
其实是用来渲染页面的,也就是说将程序返回的结果填入到具体的模板里面,生成具体的视图文件,好比:jsp,ftl,html等。
可是这里又会牵扯出两个问题:
固然,这两个问题也就是本小节说的ViewResolver
须要解决的问题。大致分为两种:
上面两种是用的最多的两种,InternalResourceViewResolver
用来解析jsp,而FreeMarkerViewResolver
则是针对FreeMarker。
BeanNameViewResolver
须要同时使用视图名和对应的local来解析视图。它须要将每个视图名和对应的视图类型配置到相应的properties文件中。(后面讲组件实现细节时给出列子)
XmlViewResolver
XmlViewResolver和BeanNameViewResolver有点差很少,BeanNameViewResolver使用的是xml格式的配置文件。
ResourceBundleViewResolver
这个其实就是根据viewName从Spring容器中查找bean,再根据这个bean来找到对应的视图。
在上面的ViewResolver
中提到,解析视图须要两个参数,一个是String类型的逻辑视图名,另一个是local。LocalResolver
的做用就是从request中解析出local的。
public interface LocaleResolver {
Locale resolveLocale(HttpServletRequest request);
void setLocale(HttpServletRequest request, HttpServletResponse response, Locale local);
}
复制代码
第一个方法是从request中解析出local,第二个方法是将local设置到request中。
关于local大多数状况下都是用来作国际化处理的。
解析主题的。这个我平时除了SpringMVC本身提供的功能外,不多本身去扩展使用,即便是换主题也没有作过。不过既然存在确定是有存在的缘由的。对于咱们常见的网页界面活着手机界面来讲,一套主题无非就是换一套图片,活着css样式文件等等。咱们经过ThemeResolver
这个就能够实现这样的功能。具体使用其实也就是配一套properties文件供系统在不一样的时候读取切换;固然使用这个也是能够实现国际化的。
public interface ThemeResolver {
String resolveThemeName(HttpServletRequest request);
void setThemeName(HttpServletRequest request, HttpServletResponse response, String themeName);
}
复制代码
这个其实仍是挺有意思的,就是将request请求转换为视图名称。
public interface RequestToViewNameTranslator {
String getViewName(HttpServletRequest request) throws Exception;
}
复制代码
RequestToViewNameTranslator
只有一个默认的实现类DefaultRequestToViewNameTranslator
。
在DefaultRequestToViewNameTranslator
具体实现了getViewName(HttpServletRequest request)方法:
public String getViewName(HttpServletRequest request) {
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
return this.prefix + this.transformPath(lookupPath) + this.suffix;
}
复制代码
主要是委派给urlPathHelper帮助类获得请求的后缀名称,好比经过 请求路径好比/glmapper/login.do转换获得/login.do ;具体怎么转换成视图也会在后面的组件介绍中给出具体的例子。
这个相应小伙伴们也不陌生,作网站多多少少会涉及到文件上传。MultipartResolver
就是用来处理上传请求的。其处理方式就是将request包装成MultipartHttpServletRequest
。而后咱们就能够用MultipartHttpServletRequest
这个直接调用getFile获取的文件了。
这个在redirect是进行参数传递须要用到。
public interface FlashMapManager {
FlashMap retrieveAndUpdate(HttpServletRequest request, HttpServletResponse response);
void saveOutputFlashMap(FlashMap flashMap, HttpServletRequest request, HttpServletResponse response);
}
复制代码
retrieveAndUpdate
这个方法是用来恢复参数的,对于恢复过的和超时的参数将都会被删除掉。
saveOutputFlashMap
这个方法是用来保存参数的。
FlashMapManager
的默认实现机制中参数的存储是放在session中的。我以前在一个项目中就有遇到过这种状况,对于一些咱们不想暴露在url中的参数,在进行请求转发时,可使用@RedirectAttributes将参数保存,而后在下一个处理器中获取到。
本篇主要是来对九大组件作一个笼统的介绍,细节实现及案例均不涉及;在后续的SpringMVC源码系列中对各个组件的实现细节分析时再一探究竟吧。