美文网首页Spring 源码
springMVC(8) ViewResolver实现之Inte

springMVC(8) ViewResolver实现之Inte

作者: 谷和阿秋 | 来源:发表于2018-01-12 21:18 被阅读314次

    前言

    为了能够对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实现之Inte

        本文链接:https://www.haomeiwen.com/subject/uukqoxtx.html