springMVC(8) ViewResolver实现之InternalResourceViewResolver

前言

为了能够对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链的最后一环。

你可能感兴趣的:(springMVC(8) ViewResolver实现之InternalResourceViewResolver)