上一节看完了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源码框架,绝对可以运行。
Spring MVC源码深度剖析开源架构源码2021.pdf
Mastering Spring MVC 4(2015.09)源码
Spring mvc、 Spring、 Spring jdbc 整合实例源码
Spring MVC是Spring框架中用于Web应用快速开发的一个模块,其中的MVC是Model-View-Controller的缩写。作为当今业界最主流的Web开发框架,Spring MVC已经成为当前最热门的开发技能,同时也广泛用于桌面开发领域。 ...
以下这个学习案例是我最近学习Spring MVC时跟从一本 书上的示例,原文中的示例代码有一些小错误,不过我 在调试的过程中已经给予了修正,如还有其它错误,还 请各位批评指正。 对于现有较成熟的Model-View-...
Spring MVC 基础实例源码01 我的博客上SpringMVC基础教程 实例的源码
spring mvc mybatis 整合源码,带数据库脚本,带详细注释,适合初、中、高各级开发人员使用
Spring MVC是Spring框架中用于Web应用快速开发的一个模块,其中的MVC是Model-View-Controller的缩写。作为当今业界最主流的Web开发框架,Spring MVC已经成为当前最热门的开发技能,同时也广泛用于桌面开发领域。 ...
spring MVC基础学习
十四、spring mvc 转发与重定向 十五、spring mvc 处理ajax请求 十六、spring mvc 关于写几个配置文件的说明 十七、spring mvc 如何取得Spring管理的bean 十八、spring mvc 多视图控制器 十九、 <mvc:annotation-...
学习Spring MVC,关于注解的Spring MVC,简单例子,关于控制器的Spring MVC,学习Spring,简单Spring MVC实例
通俗移动的Spring MVC入门书籍。请尊重版权,禁止用于商业目的。
Spring MVC 学习记录总结Spring MVC 是目前主流的实现MVC设计模式的框架,是Spring 框架的一个分支产品,以 Spring IoC 容器
Spring mvc jar包
十四、spring mvc 转发与重定向 十五、spring mvc 处理ajax请求 十六、spring mvc 关于写几个配置文件的说明 十七、spring mvc 如何取得Spring管理的bean 十八、spring mvc 多视图控制器 十九、 <mvc:annotation-...
Spring.MVC-A.Tutorial-Spring.MVC学习指南 高清可复制版PDF
spring mvc mybatis项目源码
本文详细介绍spring MVC的原理和开发心得体会。