上一节看完了ViewResolver解析视图名产生View的过程,这就到了最后的流程View执行它的render方法,实现我们到视图的跳转,对不起,前两篇都忘了说了,主要是学习札记,整个过程解释的不多其实,如果愿意看下去的朋友,我只是提供看过程的思路,spring给的注释都很通俗易懂,加上我的部分解释,应该很清楚的我想。
view.render(mv.getModelInternal(), request, response);
下面来看AbstractView中的render方法,并慢慢分析它的意义:
public void render(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);
}
// Consolidate static and dynamic model attributes.
Map<String, Object> mergedModel =
new HashMap<String, Object>(this.staticAttributes.size() + (model != null ? model.size() : 0));
mergedModel.putAll(this.staticAttributes);
if (model != null) {
mergedModel.putAll(model);
}
// Expose RequestContext?
if (this.requestContextAttribute != null) {
mergedModel.put(this.requestContextAttribute, createRequestContext(request, response, mergedModel));
}
prepareResponse(request, response);
renderMergedOutputModel(mergedModel, request, response);
}
model参数就是ModelAndView对象mv中存放
/** Model Map */
private ModelMap model;
ModelMap:
public class ModelMap extends LinkedHashMap<String, Object>
render方法的首要作用就是将model的键值对属性和View类中的属性staticAttributes整合在一起,什么是静态属性呢~类似视图的页眉、页脚的固定信息等,它们可以固定不变,所以可以直接写在配置文件中。
在***-servlet.xml中,我们配置View的bean时,我们可以为视图定义
<property name="attributesCSV">
<value>author=sha0k,copyRight=iteye</value>
</property>
而这种固定的信息就将被解析为View类的staticAttributtes
/**
* Set static attributes as a CSV string.
* Format is: attname0={value1},attname1={value1}
* <p>"Static" attributes are fixed attributes that are specified in
* the View instance configuration. "Dynamic" attributes, on the other hand,
* are values passed in as part of the model.
*/
public void setAttributesCSV(String propString) throws IllegalArgumentException {
if (propString != null) {
StringTokenizer st = new StringTokenizer(propString, ",");
while (st.hasMoreTokens()) {
String tok = st.nextToken();
int eqIdx = tok.indexOf("=");
if (eqIdx == -1) {
throw new IllegalArgumentException("Expected = in attributes CSV string '" + propString + "'");
}
if (eqIdx >= tok.length() - 2) {
throw new IllegalArgumentException(
"At least 2 characters ([]) required in attributes CSV string '" + propString + "'");
}
String name = tok.substring(0, eqIdx);
String value = tok.substring(eqIdx + 1);
// Delete first and last characters of value: { and }
value = value.substring(1);
value = value.substring(0, value.length() - 1);
addStaticAttribute(name, value);
}
}
}
通读这个方法的代码,就可以看到它对property value string的解析过程,注意最后一行代码addStaticAttributte。。。
public void addStaticAttribute(String name, Object value) {
this.staticAttributes.put(name, value);
}
到此就很好理解staticAttributtes了。。。。
createRequestContext
这里请先跳过,我也没懂,源码涉及了另外一个类。。。
/**
* Prepare the given response for rendering.
* <p>The default implementation applies a workaround for an IE bug
* when sending download content via HTTPS.
* @param request current HTTP request
* @param response current HTTP response
*/
protected void prepareResponse(HttpServletRequest request, HttpServletResponse response) {
if (generatesDownloadContent()) {
response.setHeader("Pragma", "private");
response.setHeader("Cache-Control", "private, must-revalidate");
}
}
这个方法的主要内容在于generatesDownloadContent:
/**
* Return whether this view generates download content
* (typically binary content like PDF or Excel files).
* <p>The default implementation returns <code>false</code>. Subclasses are
* encouraged to return <code>true</code> here if they know that they are
* generating download content that requires temporary caching on the
* client side, typically via the response OutputStream.
* @see #prepareResponse
* @see javax.servlet.http.HttpServletResponse#getOutputStream()
*/
protected boolean generatesDownloadContent() {
return false;
}
根据注释就可以看出,这段准备response的代码其实就做了一件事情,判断我们的响应输出是不是下载内容~~~download content!!!这就算懂了,继续了哦
renderMergedOutputModel这个方法,AbstractView类并没有实现它,在它里面是一个抽象方法,它的子类即InternalResourceView的父类AbstractUrlBasedView类也没有实现,所以我们就将代码的注意力跳转到InternalResourceView的renderMergedOutputModel方法中。
/**
* Render the internal resource given the specified model.
* This includes setting the model as request attributes.
*/
@Override
protected void renderMergedOutputModel(
Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
// Determine which request handle to expose to the RequestDispatcher.
HttpServletRequest requestToExpose = getRequestToExpose(request);
// Expose the model object as request attributes.
exposeModelAsRequestAttributes(model, requestToExpose);
// Expose helpers as request attributes, if any.
exposeHelpers(requestToExpose);
// Determine the path for the request dispatcher.
String dispatcherPath = prepareForRendering(requestToExpose, response);
// Obtain a RequestDispatcher for the target resource (typically a JSP).
RequestDispatcher rd = requestToExpose.getRequestDispatcher(dispatcherPath);
if (rd == null) {
throw new ServletException(
"Could not get RequestDispatcher for [" + getUrl() + "]: check that this file exists within your WAR");
}
// If already included or response already committed, perform include, else forward.
if (useInclude(requestToExpose, response)) {
response.setContentType(getContentType());
if (logger.isDebugEnabled()) {
logger.debug("Including resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
}
rd.include(requestToExpose, response);
}
else {
// Note: The forwarded resource is supposed to determine the content type itself.
exposeForwardRequestAttributes(requestToExpose);
if (logger.isDebugEnabled()) {
logger.debug("Forwarding to resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
}
rd.forward(requestToExpose, response);
}
}
来说重点了,我跳过的要么是根据注释就能懂的,跳到源码就更容易了,要么是根本看不懂的。。。。嘿嘿,下面的又回到了AbstractView类的方法中了,因为它的子类并没有重写它
/**
* Expose the model objects in the given map as request attributes.
* Names will be taken from the model Map.
* This method is suitable for all resources reachable by {@link javax.servlet.RequestDispatcher}.
* @param model Map of model objects to expose
* @param request current HTTP request
*/
protected void exposeModelAsRequestAttributes(Map<String, Object> model, HttpServletRequest request) throws Exception {
for (Map.Entry<String, Object> entry : model.entrySet()) {
String modelName = entry.getKey();
Object modelValue = entry.getValue();
if (modelValue != null) {
request.setAttribute(modelName, modelValue);
if (logger.isDebugEnabled()) {
logger.debug("Added model object '" + modelName + "' of type [" + modelValue.getClass().getName() +
"] to request in view with name '" + getBeanName() + "'");
}
}
else {
request.removeAttribute(modelName);
if (logger.isDebugEnabled()) {
logger.debug("Removed model object '" + modelName +
"' from request in view with name '" + getBeanName() + "'");
}
}
}
}
根据上面的代码通读后,可以看懂,原来跟字面意思一样就是说暴露Model,暴露给谁呢?暴露给HttpSerlvetRequest,也就是把Model里的属性全部加入到request中,原来我们能在jsp页面用request访问我们添加到Model里的属性就是这里实现的啊~~~~哈哈
下面就不用我解释了,include和forwad,serlvet里的基本功~~~是不是流程明白了其实不难呢?到此整个流程就完成了,以后就要研究spring惊人的设计模式和方法了,重中之重在于 先把关键的类得看懂和看明白,下一节,就先看HandlerMapping的树结构吧
分享到:
相关推荐
Spring MVC是Java EE开发中广泛使用的一个Web框架,它是Spring框架的一部分,主要负责Model-View-Controller(MVC)架构模式的实现。本知识点将围绕Spring MVC的源码深度剖析展开,详细介绍Spring MVC的源码结构、...
标题中的"开发Spring MVC应用程序补充—程序源码下载.rar_spring_spring mvc_spring mvc 源码_sp"表明这是一个关于Spring MVC框架的开发教程,其中包含了源代码供学习者参考。Spring MVC是Spring框架的一个核心组件...
总的来说,"Mastering Spring MVC 4(2015.09)源码"提供了深入学习Spring MVC的机会,你可以通过阅读和分析源码来了解如何配置DispatcherServlet、怎样编写控制器、如何进行数据绑定与验证,以及如何利用拦截器等特性...
Spring MVC 是一个基于Java的轻量级Web应用框架,它为构建Web应用程序提供模型-视图-控制器(MVC)架构。Spring MVC的核心是解耦应用程序的各个组件,使其能够独立工作并易于测试。在本源码分析中,我们将探讨Spring...
【Spring5MVC源码分析】 Spring MVC 是一个基于Java的、用于构建Web应用程序的、高度可插拔的MVC框架,它是Spring Framework的重要组成部分。Spring MVC的核心目标是简化前端控制器的开发,使得开发者可以专注于...
13. **View Technologies**:Spring MVC支持多种视图技术,如JSP、Thymeleaf、FreeMarker等,可以根据项目需求选择。 14. **RESTful API**:Spring MVC通过`@RestController`和`@RequestMapping`可以轻松创建...
- 学习Spring MVC和MyBatis的整合,可以参考官方文档、教程和开源项目的源码。 - 通过调试源码,理解其实现原理,有助于提升实战技能。 总结,这个压缩包提供了一个完整的Spring MVC和MyBatis整合的示例,包含了...
首先,Spring MVC的核心设计理念是模型-视图-控制器(Model-View-Controller)架构模式。在该模式中,模型负责业务逻辑处理,视图负责展示数据,而控制器则作为模型和视图之间的桥梁,接收用户请求并调用相应的服务...
### Spring MVC 学习指南详解 #### 一、Spring MVC 概述 Spring MVC 是 Spring 框架的一部分,主要用于构建基于 Model-View-Controller (MVC) 设计模式的 Web 应用程序。它提供了丰富的功能来简化 Web 开发过程,...
《精通Spring MVC 4》源码是一份宝贵的资源,它为开发者提供了深入理解Spring MVC这一流行Web框架的机会。Spring MVC是Spring框架的一部分,专门用于构建高效、可维护的Web应用程序。通过阅读和研究这些源码,我们...
Spring MVC、Spring和Spring JDBC是Java开发中非常重要的三大框架,它们构成了Spring框架的核心部分,广泛应用于企业级应用开发。本实例源码旨在提供一个整合这三者的基础模板,帮助开发者理解和掌握它们之间的协同...
1. **MVC架构**:Spring MVC遵循MVC模式,将应用程序分为Model(模型)、View(视图)和Controller(控制器)三个部分。Model处理业务逻辑,View负责显示结果,Controller接收用户请求并协调Model和View。 2. **...
Spring MVC是Spring框架的一个核心模块,专为构建Web应用程序而设计。它提供了模型-视图-控制器(MVC)架构,使开发者能够有效地分离业务逻辑、数据处理和用户界面。在"Spring MVC 4.2.3"版本中,我们看到了一系列的...
Spring MVC 是一个广泛使用的 Java Web 开发框架,它实现了MVC(Model-View-Controller)设计模式,使得开发者可以更高效地构建可维护且松耦合的Web应用程序。在这个学习记录总结中,我们将深入理解Spring MVC的核心...
这个源码实例应该是为了帮助开发者深入理解Spring MVC的工作原理和实现机制。下面,我们将详细探讨Spring MVC的关键知识点。 1. **DispatcherServlet**: 作为Spring MVC的核心组件,DispatcherServlet负责接收HTTP...
Spring MVC的核心是MVC模式,它将应用程序分为三个主要部分:模型、视图和控制器。模型负责管理应用程序的数据和业务逻辑,视图负责呈现数据,而控制器处理用户的请求,协调模型和视图。 **2. 处理器映射器与处理器...
Spring MVC 是一款强大的Java Web开发框架,用于构建高效、可维护和模块化的Web应用程序。它作为Spring框架的一...通过学习这个教程,你可以提高你的Web开发技能,更好地利用Spring MVC来构建高质量的Java Web应用。
DispatcherServlet 是 Spring MVC 框架的核心组件,它负责转发每一个 Request 请求给相应的 Handler,Handler 处理以后再返回相应的视图(View)和模型(Model)。DispatcherServlet 是继承自 HttpServlet 的,既然 ...
源码调试是学习Spring MVC的一个重要环节,它能帮助开发者理解框架内部的执行流程。通过设置断点,查看变量状态,跟踪方法调用,可以深入理解Spring MVC如何处理请求、如何进行依赖注入以及如何与视图交互。这种能力...