前言
为了能够对ViewResolver能够有一个更深入的理解,这次我又选择了jsp的解析部分InternalResourceViewResolver来阅读。可以从下面看到,与VelocityViewResolver类似的,InternalResourceViewResolver也同样继承了UrlBasedViewResolver类。
类图
AbstractCachingViewResolver类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| 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) { 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); } }
|
1 2 3
| protected View createView(String viewName, Locale locale) throws Exception { return loadView(viewName, locale); }
|
1
| protected abstract View loadView(String viewName, Locale locale) throws Exception;
|
可以看到解析viewName的过程是通过子类重写loadView来实现的。
UrlBasedViewResolver类
1 2 3 4 5
| 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方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 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类
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 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链的最后一环。