前言
为了能够对ViewResolver能够有一个更深入的理解,这次我又选择了jsp的解析部分InternalResourceViewResolver来阅读。可以从下面看到,与VelocityViewResolver类似的,InternalResourceViewResolver也同样继承了UrlBasedViewResolver类。
类图
InternalResourceViewResolver类图AbstractCachingViewResolver类
public View resolveViewName(String viewName, Locale locale) throws Exception {
if (!isCache()) {
return createView(viewName, locale);
}
else {
Object cacheKey = getCacheKey(viewName, locale);
View view = this.viewAccessCache.get(cacheKey);
if (view == null) {
synchronized (this.viewCreationCache) {
view = this.viewCreationCache.get(cacheKey);
if (view == null) {
// Ask the subclass to create the View object.
view = createView(viewName, locale);
if (view == null && this.cacheUnresolved) {
view = UNRESOLVED_VIEW;
}
if (view != null) {
this.viewAccessCache.put(cacheKey, view);
this.viewCreationCache.put(cacheKey, view);
if (logger.isTraceEnabled()) {
logger.trace("Cached view [" + cacheKey + "]");
}
}
}
}
}
return (view != UNRESOLVED_VIEW ? view : null);
}
}
protected View createView(String viewName, Locale locale) throws Exception {
return loadView(viewName, locale);
}
protected abstract View loadView(String viewName, Locale locale) throws Exception;
可以看到解析viewName的过程是通过子类重写loadView来实现的。
UrlBasedViewResolver类
protected View loadView(String viewName, Locale locale) throws Exception {
AbstractUrlBasedView view = buildView(viewName);
View result = applyLifecycleMethods(viewName, view);
return (view.checkResource(locale) ? result : null);
}
这部分需要注意,InternalResourceView的checkResource方法默认为返回true。而Velocity则会有相应的判断资源是否存在的措施。
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());
if (this.exposePathVariables != null) {
view.setExposePathVariables(exposePathVariables);
}
return view;
}
InternalResourceViewResolver类
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;
}
InternalResourceViewResolver类中的buildView方法中首先执行了父类的buildView方法。之后又进行了一些view的属性设置。
总结
我们可以发现InternalResourceViewResolver与VelocityViewResolver的除了view属性设置不同外,有一个最大区别就是,InternalResourceViewResolver的checkResource方法不会起到拦截作用,即使没有相应的资源存在。所以InternalResourceViewResolver在配置时应该作为ViewResolver链的最后一环。
网友评论