`
sha0k
  • 浏览: 84876 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

Spring MVC 源码学习札记(三)看看View怎么做到视图转发的

 
阅读更多

上一节看完了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的树结构吧

 

 

 

 

 

 

 

 

 

 

2
0
分享到:
评论

相关推荐

    Spring MVC源码深度剖析开源架构源码2021.pdf

    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应用程序补充—程序源码下载.rar_spring_spring mvc_spring mvc 源码_sp"表明这是一个关于Spring MVC框架的开发教程,其中包含了源代码供学习者参考。Spring MVC是Spring框架的一个核心组件...

    Mastering Spring MVC 4(2015.09)源码

    总的来说,"Mastering Spring MVC 4(2015.09)源码"提供了深入学习Spring MVC的机会,你可以通过阅读和分析源码来了解如何配置DispatcherServlet、怎样编写控制器、如何进行数据绑定与验证,以及如何利用拦截器等特性...

    spring mvc框架源码

    Spring MVC 是一个基于Java的轻量级Web应用框架,它为构建Web应用程序提供模型-视图-控制器(MVC)架构。Spring MVC的核心是解耦应用程序的各个组件,使其能够独立工作并易于测试。在本源码分析中,我们将探讨Spring...

    Spring5MVC源码.docx

    【Spring5MVC源码分析】 Spring MVC 是一个基于Java的、用于构建Web应用程序的、高度可插拔的MVC框架,它是Spring Framework的重要组成部分。Spring MVC的核心目标是简化前端控制器的开发,使得开发者可以专注于...

    Spring MVC 基础实例源码01

    13. **View Technologies**:Spring MVC支持多种视图技术,如JSP、Thymeleaf、FreeMarker等,可以根据项目需求选择。 14. **RESTful API**:Spring MVC通过`@RestController`和`@RequestMapping`可以轻松创建...

    spring mvc mybatis 整合源码,带数据库脚本,带详细注释

    - 学习Spring MVC和MyBatis的整合,可以参考官方文档、教程和开源项目的源码。 - 通过调试源码,理解其实现原理,有助于提升实战技能。 总结,这个压缩包提供了一个完整的Spring MVC和MyBatis整合的示例,包含了...

    Spring.MVC-A.Tutorial-Spring.MVC学习指南 高清可复制版PDF

    首先,Spring MVC的核心设计理念是模型-视图-控制器(Model-View-Controller)架构模式。在该模式中,模型负责业务逻辑处理,视图负责展示数据,而控制器则作为模型和视图之间的桥梁,接收用户请求并调用相应的服务...

    Spring MVC学习指南

    ### Spring MVC 学习指南详解 #### 一、Spring MVC 概述 Spring MVC 是 Spring 框架的一部分,主要用于构建基于 Model-View-Controller (MVC) 设计模式的 Web 应用程序。它提供了丰富的功能来简化 Web 开发过程,...

    《精通Spring MVC 4》源码

    《精通Spring MVC 4》源码是一份宝贵的资源,它为开发者提供了深入理解Spring MVC这一流行Web框架的机会。Spring MVC是Spring框架的一部分,专门用于构建高效、可维护的Web应用程序。通过阅读和研究这些源码,我们...

    Spring mvc、 Spring、 Spring jdbc 整合实例源码

    Spring MVC、Spring和Spring JDBC是Java开发中非常重要的三大框架,它们构成了Spring框架的核心部分,广泛应用于企业级应用开发。本实例源码旨在提供一个整合这三者的基础模板,帮助开发者理解和掌握它们之间的协同...

    看透spring mvc源代码分析与实践扫描版带目录+源码

    1. **MVC架构**:Spring MVC遵循MVC模式,将应用程序分为Model(模型)、View(视图)和Controller(控制器)三个部分。Model处理业务逻辑,View负责显示结果,Controller接收用户请求并协调Model和View。 2. **...

    Spring MVC 4.2.3

    Spring MVC是Spring框架的一个核心模块,专为构建Web应用程序而设计。它提供了模型-视图-控制器(MVC)架构,使开发者能够有效地分离业务逻辑、数据处理和用户界面。在"Spring MVC 4.2.3"版本中,我们看到了一系列的...

    Spring MVC 学习记录总结1

    Spring MVC 是一个广泛使用的 Java Web 开发框架,它实现了MVC(Model-View-Controller)设计模式,使得开发者可以更高效地构建可维护且松耦合的Web应用程序。在这个学习记录总结中,我们将深入理解Spring MVC的核心...

    spring mvc源码实例

    这个源码实例应该是为了帮助开发者深入理解Spring MVC的工作原理和实现机制。下面,我们将详细探讨Spring MVC的关键知识点。 1. **DispatcherServlet**: 作为Spring MVC的核心组件,DispatcherServlet负责接收HTTP...

    Spring MVC 4.2.4.RELEASE 中文文档

    Spring MVC的核心是MVC模式,它将应用程序分为三个主要部分:模型、视图和控制器。模型负责管理应用程序的数据和业务逻辑,视图负责呈现数据,而控制器处理用户的请求,协调模型和视图。 **2. 处理器映射器与处理器...

    最全最经典spring-mvc教程

    Spring MVC 是一款强大的Java Web开发框架,用于构建高效、可维护和模块化的Web应用程序。它作为Spring框架的一...通过学习这个教程,你可以提高你的Web开发技能,更好地利用Spring MVC来构建高质量的Java Web应用。

    spring MVC配置详解

    DispatcherServlet 是 Spring MVC 框架的核心组件,它负责转发每一个 Request 请求给相应的 Handler,Handler 处理以后再返回相应的视图(View)和模型(Model)。DispatcherServlet 是继承自 HttpServlet 的,既然 ...

    spring-mvc 基础功能之源码debug

    源码调试是学习Spring MVC的一个重要环节,它能帮助开发者理解框架内部的执行流程。通过设置断点,查看变量状态,跟踪方法调用,可以深入理解Spring MVC如何处理请求、如何进行依赖注入以及如何与视图交互。这种能力...

Global site tag (gtag.js) - Google Analytics