DispatherServlet类分析
首先,我们看DispatherServlet类中的初始化试图解析器的方法  我们逐步来看代码:
this.viewResolvers = null;
if (this.detectAllViewResolvers) {
在容器的上下文中寻找所有的视图解析器
Map<String, ViewResolver> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, ViewResolver.class, true, false);
if (!matchingBeans.isEmpty()) {
this.viewResolvers = new ArrayList<>(matchingBeans.values());
AnnotationAwareOrderComparator.sort(this.viewResolvers);
}
}
但是通常detectAllViewResolvers的默认值会设置成为TRUE,默认会加载所有视图解析器 
Map<String, ViewResolver> matchingBeans这个Map集合,通常寻找的所有的视图解析器之后全部存储到Map集合中,名字和本身的对象存储,之后调用AnnotationAwareOrderComparator.sort(this.viewResolvers)方法,对所有的视图解析器进行排序,按照本身的order属性
   
之后发送请求之后,中央控制器收到请求之后,会调用service方法,紧接着调用processRequest方法,之后进入到DispatherServlet类中的doService方法中,之后调用如下图: 
resolveViewName方法:
我们细看resolveViewName方法:
public View resolveViewName(String viewName, Locale locale) throws Exception {
RequestAttributes attrs = RequestContextHolder.getRequestAttributes();
Assert.state(attrs instanceof ServletRequestAttributes, "No current ServletRequestAttributes");
List<MediaType> requestedMediaTypes = getMediaTypes(((ServletRequestAttributes) attrs).getRequest());
if (requestedMediaTypes != null) {
List<View> candidateViews = getCandidateViews(viewName, locale, requestedMediaTypes);
View bestView = getBestView(candidateViews, requestedMediaTypes, attrs);
if (bestView != null) {
return bestView;
}
}
getCandidateViews方法
进入getCandidateViews方法:
for (ViewResolver viewResolver : this.viewResolvers) {
View view = viewResolver.resolveViewName(viewName, locale);
if (view != null) {
candidateViews.add(view);
}

AbstractUrlBasedView 类
AbstractUrlBasedView 类中:
protected View loadView(String viewName, Locale locale) throws Exception {
AbstractUrlBasedView view = buildView(viewName);
View result = applyLifecycleMethods(viewName, view);
return (view.checkResource(locale) ? result : null);
}
public boolean checkResource(Locale locale) throws Exception {
return true;
}
FreeMarkerView类
FreeMarkerView类中:
public boolean checkResource(Locale locale) throws Exception {
String url = getUrl();
Assert.state(url != null, "'url' not set");
try {
getTemplate(url, locale);
return true;
}
catch (FileNotFoundException ex) {
return false;
}
catch (ParseException ex) {
throw new ApplicationContextException("Failed to parse [" + url + "]", ex);
}
catch (IOException ex) {
throw new ApplicationContextException("Failed to load [" + url + "]", ex);
}
}
checkResource方法有非常好的检查view,Thymeleaf中并没有检查的方法
getBestView方法
进入getBestView方法:  当每一个视图解析器的mediaType与候选视图的ContentType相同时就返回,当有多个视图都相同时返回第一个,按视图解析器的order优先级来排序 
详细SpringMVC工作流程图

|