ViewResolver
作用:根据viewName找到view对象
SpringMVC用于处理视图最重要的两个接口是ViewResolver和View。ViewResolver的主要作用是把一个逻辑上的视图名称解析为一个真正的视图,SpringMVC中用于把View对象呈现给客户端的是View对象本身,而ViewResolver只是把逻辑视图名称解析为对象的View对象。View接口的主要作用是用于处理视图,然后返回给客户端。
ViewResolver的提供的接口的主要功能是生成View对象,源码如下:
public interface ViewResolver {
/**
* Resolve the given view by name.
* <p>Note: To allow for ViewResolver chaining, a ViewResolver should
* return {@code null} if a view with the given name is not defined in it.
* However, this is not required: Some ViewResolvers will always attempt
* to build View objects with the given name, unable to return {@code null}
* (rather throwing an exception when View creation failed).
* @param viewName name of the view to resolve
* @param locale Locale in which to resolve the view.
* ViewResolvers that support internationalization should respect this.
* @return the View object, or {@code null} if not found
* (optional, to allow for ViewResolver chaining)
* @throws Exception if the view cannot be resolved
* (typically in case of problems creating an actual View object)
*/
View resolveViewName(String viewName, Locale locale) throws Exception;
}
Spring为我们提供了非常多的视图解析器,下面将列举一些视图解析器。一句话概述下,不了解的麻烦看我写的详细的视图解析器链接
1.AbstractCachingViewResolver 基于缓存的抽象视图解析器
2.UrlBasedViewResolver 实现了缓存 提供了prefix suffix拼接的url视图解析器。
3、InternalResourceViewResolver 基于url 的内部资源视图解析器。
4.XmlViewResolver 基于xml的缓存视图解析器
5.BeanNameViewResolver beanName来自容器,并且不支持缓存。
6.ResourceBundleViewResolver 这个有点复杂,自己看后面的链接
7.FreeMarkerViewResolver、VolocityViewResolver 都基于url 但会解析成特定的view
如果对常见的ViewResolver不了解点这里—》
关于该接口的学习我们明白两件事就可以了
1.关于viewResolver的注册
2.resolveviewName方法的实现
首先第一个问题
它是在DispatcherServlet的init阶段完成的,简单了解下就可以
第二个问题
则是ViewResolver接口的resolveviewName方法
在开发的一套springMVC系统中是可以使用多个视图的,当然就需要配置多个视图解析器了,ViewResolverComposite简单来说就是使用简单的List来保存你配置使用的视图解析器。
iewResolverComposite中定义了两个变量:
(1)private final List viewResolvers = new ArrayList();用来存储所有的视图解析器
(2)private int order 用来配置视图解析器的使用顺序。
主要是一个视图解析器集合
public class ViewResolverComposite implements ViewResolver, Ordered, InitializingBean,
ApplicationContextAware, ServletContextAware {
//用来存储所有的视图解析器
private final List<ViewResolver> viewResolvers = new ArrayList<ViewResolver>();
//设置视图解析器的执行顺序
private int order = Ordered.LOWEST_PRECEDENCE;
//设置视图解析器
public void setViewResolvers(List<ViewResolver> viewResolvers) {
this.viewResolvers.clear();
if (!CollectionUtils.isEmpty(viewResolvers)) {
this.viewResolvers.addAll(viewResolvers);
}
}
//获取所有的视图解析器
public List<ViewResolver> getViewResolvers() {
return Collections.unmodifiableList(this.viewResolvers);
}
//设置执行顺序
public void setOrder(int order) {
this.order = order;
}
@Override
public int getOrder() {
return this.order;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
for (ViewResolver viewResolver : this.viewResolvers) {
if (viewResolver instanceof ApplicationContextAware) {
((ApplicationContextAware)viewResolver).setApplicationContext(applicationContext);
}
}
}
@Override
public void setServletContext(ServletContext servletContext) {
for (ViewResolver viewResolver : this.viewResolvers) {
if (viewResolver instanceof ServletContextAware) {
((ServletContextAware)viewResolver).setServletContext(servletContext);
}
}
}
//初始化视图解析器
@Override
public void afterPropertiesSet() throws Exception {
for (ViewResolver viewResolver : this.viewResolvers) {
if (viewResolver instanceof InitializingBean) {
((InitializingBean) viewResolver).afterPropertiesSet();
}
}
}
//生成View对象
@Override
public View resolveViewName(String viewName, Locale locale) throws Exception {
for (ViewResolver viewResolver : this.viewResolvers) {
View view = viewResolver.resolveViewName(viewName, locale);
if (view != null) {
return view;
}
}
return null;
}
} solves链表遍历 找到一个能获取view对象的ViewResolver,并返回该view对象
/**
* Resolve the given view name into a View object (to be rendered).
* <p>The default implementations asks all ViewResolvers of this dispatcher.
* Can be overridden for custom resolution strategies, potentially based on
* specific model attributes or request parameters.
* @param viewName the name of the view to resolve
* @param model the model to be passed to the view
* @param locale the current locale
* @param request current HTTP servlet request
* @return the View object, or {@code null} if none found
* @throws Exception if the view cannot be resolved
* (typically in case of problems creating an actual View object)
* @see ViewResolver#resolveViewName
*/
protected View resolveViewName(String viewName, Map<String, Object> model, Locale locale,
HttpServletRequest request) throws Exception {
for (ViewResolver viewResolver : this.viewResolvers) {
View view = viewResolver.resolveViewName(viewName, locale);
if (view != null) {
return view;
}
}
return null;
}
然后看它的resolveViewName方法
接下来我们通过介绍常见InternalResourceViewResolver来对ViewResolver的运行流程有一个简单的了解和认识。
1、首先执行的流程开始在DispatcherServlet的render函数中,会调用resolverViewName来获取View对象。
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
// Determine locale for request and apply it to the response.
........
View view;
........
//获得视图
view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
.......
}
resolveViewName的主要工作就是从配置的所有视图解析器中查找一个可以生成View对象的视图解析器。
protected View resolveViewName(String viewName, Map<String, Object> model, Locale locale,
HttpServletRequest request) throws Exception {
for (ViewResolver viewResolver : this.viewResolvers) {
View view = viewResolver.resolveViewName(viewName, locale);
if (view != null) {
return view;
}
}
return null;
}
这里选取的是InternalResourceViewResolver。其他的方法类似。
在InternalResourceViewResolver中的操作就是将viewName和locale设置到View对象中,这样就完成了View对象的创建。