第一节我们看到了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;
}
分享到:
相关推荐
View,ViewResolver
6 <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 7 <property name="prefix" value="/WEB-INF/jsp/" /> 8 <property name="suffix" value=".jsp" /> 9 ...
Spring Web model-view-controller (MVC)框架是围绕 DispatcherServlet 设计的,并分发请求到处理程序(handler),Spring MVC支持可配置的处理程序映射(handler mapping),视图解析(view resolution)、 区域设置...
5)Spring MVC处理流程 a.首先客户端发出spring mvc请求,请求到达DispatcherServlet主控制器处理(前端控制器) b.主控制器调用HandlerMapping组件,根据请求不同调用Controller处理器 c.主控制器调用Controller方法...
5、 ModelAndView的逻辑视图名交给ViewResolver解析器, ViewResolver解析器把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换其他视图技术; 6、 View会根据传进来的Model模型数据进行渲染,此处的...
Spring MVC框架围绕DispatcherServlet这个核心展开,DispatcherServlet的作用是截获请求并组织一系列组件共同完成请求的处理工作。 JavaServer Faces (JSF) 是一种用于构建 Web 应用程序的新标准 Java 框架。它...
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/"> <property name="suffix" value=".jsp"> <!-- prefix+modelAndView+...
第二篇 俯视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...
Spring MVC 内置了 Requestmapping、HandlerMapping 和 ViewResolver 等组件,可以简化开发流程。MyBatis 作为持久层框架,负责处理数据库操作。 在安全性方面,该网站采用了 SSL 证书进行加密传输,并实现了用户...
1.spring mvc请所有的请求都提交给DispatcherServlet,它会委托应用系统的其他模块负责负责对请求进行真正的处理工作。 2.DispatcherServlet查询一个或多个HandlerMapping,找到处理请求的Controller. 3....
* 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 ...
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 MVC 内置了 Requestmapping、HandlerMapping 和 ViewResolver 等组件,可以简化开发流程。MyBatis 作为持久层框架,负责处理数据库操作。 在安全性方面,该教务管理系统采用了 SSL 证书进行加密传输,并实现...
这里是我自学 springmvc 框架的基本教程,按照这个教程可以轻松的掌握SpringMvc的搭建和使用,同时下一步本人会将 SpringMVC和数据库操作集成学习也进行分项,本次学习共八节,这里是第四节。 剩余章节,后续更新
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.0是Spring在积蓄了3年之久后,隆重推出的一个重大升级版本,进一步加强了Spring作为Java领域第一开源平台的翘楚地位。 Spring3.0引入了众多Java开发者翘首以盼的新功能和新特性,如OXM、校验及格式化框架...
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. 动态...
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/"/> <property name="suffix" value=".jsp"/> ...
SpringMVC-helloworld 这是将Spring MVC与JavaConfig结合使用以制作helloworld Web应用程序的非常基本的示例。 这的第一部分是为Web应用程序创建一个配置类。 以下是我们将要使用的配置类的示例: Configuration@...
Spring3.0是Spring在积蓄了3年之久后,隆重推出的一个重大升级版本,进一步加强了Spring作为Java领域第一开源平台的翘楚地位。 Spring3.0引入了众多Java开发者翘首以盼的新功能和新特性,如OXM、校验及格式化框架...