概述
通过上几章的介绍知道了ViewResolver的作用,即ViewResolver就是把handler返回的逻辑视图名称解析为视图View对象。进而通过View对象的视图渲染把最终的结果展现给用户。
View视图渲染的原理,简单说就是把模型数据填充到视图模板,最终交由Servlet的response进行渲染展示。
Spring MVC运用模板技术把数据和视图分开,同时提供支持很多的模板技术,比如:InternalResourceView(JstlView)、FreeMarkerView、Thymeleaf等等。
本系列文章是基于Spring5.0.5RELEASE。
源码分析
以InternalResourceView为例进行分析,该类解析jsp视图模板,主要涉及类和接口如下:
- View
View接口是Spring MVC提供的视图渲染接口,定义了render方法对给定的模型数据进行视图渲染,源码如下:
public interface View {
... ...
/** 把模型数据进行渲染 */
void render(@Nullable Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)
throws Exception;
... ...
}
- AbstractView
AbstractView是实现View接口的抽象类,实现了render方法,源码如下:
public abstract class AbstractView extends WebApplicationObjectSupport implements View, BeanNameAware {
... ...
@Override
public void render(@Nullable Map<String, ?> model, HttpServletRequest request,
HttpServletResponse response) throws Exception {
if (logger.isTraceEnabled()) {
logger.trace("Rendering view with name '" + this.beanName + "' with model " + model +
" and static attributes " + this.staticAttributes);
}
// 创建整合后需要返回给浏览器的Model
Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);
// 设置response 报文头
prepareResponse(request, response);
// 渲染数据,通过模板方法由子类实现,如InternalResourceView
renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
}
... ...
}
- InternalResourceView
该类继承自AbstractView,并实现renderMergedOutputModel方法,源码如下:
@Override
protected void renderMergedOutputModel(
Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
// 将model中的数据设置到request
exposeModelAsRequestAttributes(model, request);
// 本类中的此函数是空函数,留给子类比如JstlView去实现自定义逻辑
exposeHelpers(request);
// 跳转目的页面路径
String dispatcherPath = prepareForRendering(request, response);
// 获取跳转控制器RequestDispatcher
RequestDispatcher rd = getRequestDispatcher(request, dispatcherPath);
if (rd == null) {
throw new ServletException("Could not get RequestDispatcher for [" + getUrl() +
"]: Check that the corresponding file exists within your web application archive!");
}
// 直接返回用户资源
if (useInclude(request, response)) {
response.setContentType(getContentType());
if (logger.isDebugEnabled()) {
logger.debug("Including resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
}
rd.include(request, response);
}
// 携带request和response跳转到另一个控制器方法
else {
// Note: The forwarded resource is supposed to determine the content type itself.
if (logger.isDebugEnabled()) {
logger.debug("Forwarding to resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
}
rd.forward(request, response);
}
}
至此,View渲染视图的大致流程结束,也就是Spring MVC基本完成了整个流程,剩下的渲染工作交由Servlet去处理。
总结
本章就View视图渲染进行了简单的分析,Spring 提供了众多的View实现,有兴趣的童鞋可以继续了解。
最后创建了qq群方便大家交流,可扫描加入,同时也可加我qq:276420284,共同学习、共同进步,谢谢!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。