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

Spring MVC 源码学习札记(二)ViewResolver处理viewname

 
阅读更多

第一节我们看到了ViewResolver对ModelAndView中属性Oject view为String时,将调用方法:

	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的机制。

来看看我们第一眼能懂的,Internal产生的是JstlView,Freemarker不用说,Velocity不用说,那就从这三个类来入手。

还是过程式的代码阅读,我们去找resovlveViewName 这个方法。

在AbstractCachingViewResolver类中:

 

public View resolveViewName(String viewName, Locale locale) throws Exception {
		if (!isCache()) {
			return createView(viewName, locale);



		}
		else {
			Object cacheKey = getCacheKey(viewName, locale);
			synchronized (this.viewCache) {
				View view = this.viewCache.get(cacheKey);
				if (view == null) {
					// Ask the subclass to create the View object.
					view = createView(viewName, locale);
					this.viewCache.put(cacheKey, view);
					if (logger.isTraceEnabled()) {
						logger.trace("Cached view [" + cacheKey + "]");
					}
				}
				return view;
			}
		}
	}

 

protected View createView(String viewName, Locale locale) throws Exception {
		return loadView(viewName, locale);



	}
 
protected abstract View loadView(String viewName, Locale locale) throws Exception;//子类必须实现这个方法
 

  loadView方法又将我们带入了AbstractCachingViewResolver的子类UrlBasedViewResolver类中,可以发现UrlBasedViewResolver类中:

 

/**
	 * Overridden to implement check for "redirect:" prefix.
	 * <p>Not possible in <code>loadView</code>, since overridden
	 * <code>loadView</code> versions in subclasses might rely on the
	 * superclass always creating instances of the required view class.
	 * @see #loadView
	 * @see #requiredViewClass
	 */
	@Override
	protected View createView(String viewName, Locale locale) throws Exception {
		// If this resolver is not supposed to handle the given view,
		// return null to pass on to the next resolver in the chain.
		if (!canHandle(viewName, locale)) {
			return null;
		}
		// Check for special "redirect:" prefix.
		if (viewName.startsWith(REDIRECT_URL_PREFIX)) {
			String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length());
			return new RedirectView(redirectUrl, isRedirectContextRelative(), isRedirectHttp10Compatible());
		}
		// Check for special "forward:" prefix.
		if (viewName.startsWith(FORWARD_URL_PREFIX)) {
			String forwardUrl = viewName.substring(FORWARD_URL_PREFIX.length());
			return new InternalResourceView(forwardUrl);
		}
		// Else fall back to superclass implementation: calling loadView.
		return super.createView(viewName, locale);
	}

 这里千万别糊涂哦,这可是java基础知识多态哦。。。。

 因为在DispatcherServlet中的viewResolvers保存的都是ViewResolver的实现类的对象,那么调用接口的resolveViewName方法后,就得一层层来看这个方法了,从代码中我们看到的是只有AbstractCachingViewResolver有这个方法,那肯定调用的是它的。但是在resolveViewName中又调用了createView,那么这里调用的就是UrlBasedViewResolver的方法了。

 

所以在该方法前面的if都没得到满足时,才去显示的调用父类的createView方法。

// Else fall back to superclass implementation: calling loadView.
		return super.createView(viewName, locale);

 

这时父类的createView调用了loadView方法,而UrlBasedViewResolver又实现了这一方法,自然而然是调用它的loadView方法,而Internal暴露了buildView方法,则loadView执行时首先调用Internal的buildView。

@Override
	protected View loadView(String viewName, Locale locale) throws Exception {
		AbstractUrlBasedView view = buildView(viewName);
		View result = (View) getApplicationContext().getAutowireCapableBeanFactory().initializeBean(view, viewName);
		return (view.checkResource(locale) ? result : null);
	}

 UrlBasedViewResolver类中的buildView方法

 

protected AbstractUrlBasedView buildView(String viewName) throws Exception {
		AbstractUrlBasedView view = (AbstractUrlBasedView) BeanUtils.instantiateClass(getViewClass());
		view.setUrl(getPrefix() + viewName + getSuffix());
		String contentType = getContentType();
		if (contentType != null) {
			view.setContentType(contentType);
		}
		view.setRequestContextAttribute(getRequestContextAttribute());
		view.setAttributesMap(getAttributesMap());
		return view;
	}

  InternalResourceViewResolver的buildView方法,忽然看到这个viewClass让我眼前一亮,终于知道Freemarker去生成静态页面是怎么做到的了,用自己实现的类配置在Resolver的属性中,这样等于是做了一次拦截。

<bean id="freemarkerViewResolver"
		class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
		<property name="contentType" value="text/html;charset=gbk" />
		<property name="viewClass" value="com.sha0k.util.MyFreeMarkerView">
		</property>
		<property name="exposeRequestAttributes">
			<value>true</value>
		</property>
		<property name="exposeSessionAttributes">
			<value>true</value>
		</property>
		<property name="order">
			<value>1</value>
		</property>
		<property name="suffix" value=".ftl" />
	</bean>
 

 

@Override
	protected AbstractUrlBasedView buildView(String viewName) throws Exception {
		InternalResourceView view = (InternalResourceView) super.buildView(viewName);
		if (this.alwaysInclude != null) {
			view.setAlwaysInclude(this.alwaysInclude);
		}
		if (this.exposeContextBeansAsAttributes != null) {
			view.setExposeContextBeansAsAttributes(this.exposeContextBeansAsAttributes);
		}
		if (this.exposedContextBeanNames != null) {
			view.setExposedContextBeanNames(this.exposedContextBeanNames);
		}
		view.setPreventDispatchLoop(true);
		return view;
	}
 

 

 

 

 

 

 

 

0
0
分享到:
评论

相关推荐

    Spring MVC 解读——View,ViewResolver.zip

    View,ViewResolver

    Spring MVC 入门实例

    6 &lt;bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"&gt; 7 &lt;property name="prefix" value="/WEB-INF/jsp/" /&gt; 8 &lt;property name="suffix" value=".jsp" /&gt; 9 ...

    spring mvc 3.2 参考文档

    Spring Web model-view-controller (MVC)框架是围绕 DispatcherServlet 设计的,并分发请求到处理程序(handler),Spring MVC支持可配置的处理程序映射(handler mapping),视图解析(view resolution)、 区域设置...

    java spring mvc

    5)Spring MVC处理流程 a.首先客户端发出spring mvc请求,请求到达DispatcherServlet主控制器处理(前端控制器) b.主控制器调用HandlerMapping组件,根据请求不同调用Controller处理器 c.主控制器调用Controller方法...

    Spring MVC 学习笔记

    5、 ModelAndView的逻辑视图名交给ViewResolver解析器, ViewResolver解析器把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换其他视图技术; 6、 View会根据传进来的Model模型数据进行渲染,此处的...

    Spring MVC 员工管理系统

    Spring MVC框架围绕DispatcherServlet这个核心展开,DispatcherServlet的作用是截获请求并组织一系列组件共同完成请求的处理工作。 JavaServer Faces (JSF) 是一种用于构建 Web 应用程序的新标准 Java 框架。它...

    Spring-mvc,例题

    &lt;bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"&gt; &lt;property name="prefix" value="/"&gt; &lt;property name="suffix" value=".jsp"&gt; &lt;!-- prefix+modelAndView+...

    看透springMvc源代码分析与实践

    第二篇 俯视Spring MVC 第8章 Spring MVC之初体验84 8.1 环境搭建84 8.2 Spring MVC最简单的配置84 8.2.1 在web.xml中配置Servlet85 8.2.2 创建Spring MVC的xml配置文件85 8.2.3 创建Controller和view86 8.3...

    民宿网站管理系统java+spring.7z,架构是SSM

    Spring MVC 内置了 Requestmapping、HandlerMapping 和 ViewResolver 等组件,可以简化开发流程。MyBatis 作为持久层框架,负责处理数据库操作。 在安全性方面,该网站采用了 SSL 证书进行加密传输,并实现了用户...

    Spring面试题

    1.spring mvc请所有的请求都提交给DispatcherServlet,它会委托应用系统的其他模块负责负责对请求进行真正的处理工作。 2.DispatcherServlet查询一个或多个HandlerMapping,找到处理请求的Controller. 3....

    org.springframework.web.servlet-3.1.0.RELEASE

    * view name which will need to be resolved by a ViewResolver object; * alternatively a View object can be specified directly. The model * is a Map, allowing the use of multiple objects keyed by ...

    Spring-Reference_zh_CN(Spring中文参考手册)

    2.5.1. Spring MVC的表单标签库 2.5.2. Spring MVC合理的默认值 2.5.3. Portlet 框架 2.6. 其他特性 2.6.1. 动态语言支持 2.6.2. JMX 2.6 .3. 任务规划 2.6.4. 对Java 5(Tiger)的支持 2.7. 移植到Spring 2.0 ...

    基于spring+java的教务管理系统.7z,SSM框架

    Spring MVC 内置了 Requestmapping、HandlerMapping 和 ViewResolver 等组件,可以简化开发流程。MyBatis 作为持久层框架,负责处理数据库操作。 在安全性方面,该教务管理系统采用了 SSL 证书进行加密传输,并实现...

    spring3.0_mvc框架_04_内部实现机制_handlemapping_viewresolver_modelandView.flv

    这里是我自学 springmvc 框架的基本教程,按照这个教程可以轻松的掌握SpringMvc的搭建和使用,同时下一步本人会将 SpringMVC和数据库操作集成学习也进行分项,本次学习共八节,这里是第四节。 剩余章节,后续更新

    Spring中文帮助文档

    2.5.1. Spring MVC合理的默认值 2.5.2. Portlet 框架 2.5.3. 基于Annotation的控制器 2.5.4. Spring MVC的表单标签库 2.5.5. 对Tiles 2 支持 2.5.6. 对JSF 1.2支持 2.5.7. JAX-WS支持 2.6. 其他 2.6.1. 动态...

    Spring.3.x企业应用开发实战(完整版).part2

    Spring3.0是Spring在积蓄了3年之久后,隆重推出的一个重大升级版本,进一步加强了Spring作为Java领域第一开源平台的翘楚地位。  Spring3.0引入了众多Java开发者翘首以盼的新功能和新特性,如OXM、校验及格式化框架...

    Spring API

    2.5.1. Spring MVC合理的默认值 2.5.2. Portlet 框架 2.5.3. 基于Annotation的控制器 2.5.4. Spring MVC的表单标签库 2.5.5. 对Tiles 2 支持 2.5.6. 对JSF 1.2支持 2.5.7. JAX-WS支持 2.6. 其他 2.6.1. 动态...

    Spring3中配置DBCP,C3P0,Proxool,Bonecp数据源

    &lt;bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"&gt; &lt;property name="prefix" value="/WEB-INF/views/"/&gt; &lt;property name="suffix" value=".jsp"/&gt; ...

    springmvc-helloworld:这是一个Spring MVC Web项目,展示了如何使用JavaConfig而不是XML文件

    SpringMVC-helloworld 这是将Spring MVC与JavaConfig结合使用以制作helloworld Web应用程序的非常基本的示例。 这的第一部分是为Web应用程序创建一个配置类。 以下是我们将要使用的配置类的示例: Configuration@...

    Spring3.x企业应用开发实战(完整版) part1

    Spring3.0是Spring在积蓄了3年之久后,隆重推出的一个重大升级版本,进一步加强了Spring作为Java领域第一开源平台的翘楚地位。  Spring3.0引入了众多Java开发者翘首以盼的新功能和新特性,如OXM、校验及格式化框架...

Global site tag (gtag.js) - Google Analytics