SpringMVC源码学习经历(识图解析器篇)

(Notice:以下所有经验也是我根据网上的经验整理的,如有侵权可以联系我删除,欢迎交流和沟通,Wx:IT_Ezra,QQ 654303408。 有问题讨论也可联系我。)

(PS:SpringMVC是目前主流的Web MVC框架之一,其工作流程我在之前的文章中介绍了,下面我想重点讲一下SprignMVC的识图解析器。)

image.png

(PS:我认为最最最核心的流程:下马威)

首先,我们可以根据这个图把整个流程走一遍。首先来了一个请求,然后通过DispatcherServlet,DispatcherServlet的init加载的mapperHandler类的getHandler()方法得到handler,DispatcherServlet的init加载的RequestMappingHandlerAdapter类的handle()方法返回ModelAndView, 然后把ModelAndView传到视图解析器(InternalResourceViewResolver)解析,InternalResourceViewResolver继承了UrlBasedViewResolver类,UrlBasedViewResolver类继承AbstractCachingViewResolver抽象类,AbstractCachingViewResolver抽象类会首先createView()方法,其内部调用loadView()方法,loadView()方法里面调用了buildView()方法,然后返回一个InternalResourceView视图。

------------------------------------------------------------------------------------------------------

然后开始介绍重要的借口和类。
  • 1.View接口

视图基础接口,它的各种实现是么有状态的,所以也是线程安全的。该接口定义了两个方法。
View接口

  • 2. AbstractView抽象类

View接口的基础实现类。我们稍微介绍一下这个抽象类。
AbstractView抽象类
其中非常重要的一个方法render方法,该方法里面有一个抽象方法renderMergedOutputModel方法(AbstractView抽象类定义的抽象方法,为View接口提供的render方法服务)。
render方法
  • 3. AbstractUrlBasedView抽象类

继承自AbstractView抽象类,增加了1个类型为String的url参数。
  • 4. InternalResourceView类(重点类,我们在配置Springmvc的时候经常会看到它的配置)

继承自AbstractUrlBasedView抽象类的类,表示JSP视图。
我们看下这个类的renderMergedOutputModel方法(AbstractView抽象类定义的抽象方法,为View接口提供的render方法服务)。这个抽象类里面可一看到最后决定用include方法还是forward方法。这两个方法都是重定向方法,但是区别不同的是,惟一的不同在于:利用include()方法将HTTP请求转送给其他Servlet后,被调用的Servlet虽然可以处理这个HTTP请求,但是最后的主导权仍然是在原来的Servlet。RequestDispatcher是一个Web资源的包装器,可以用来把当前request传递到该资源,或者把新的资源包括到当前响应中。
renderMergedOutputModel

我们在SpringMVC的配置文件里面,会配置视图解析器,目前主流的就是InternalResourceView类,当然它的实现也是依赖于另一个抽象类AbstractCachingViewResolver(后文会讲到)。我们继续介绍其他类和接口

   
    
        
        
            /WEB-INF/
        
        
        
            .html
        
    
  • 5. JstlView类

JSTL视图,继承自InternalResourceView,该类大致上与InternalResourceView类一致。
  • 6. AbstractTemplateView抽象类

继承自AbstractUrlBasedView抽象类,重写了renderMergedOutputModel方法,在该方法中会调用renderMergedTemplateModel方法,renderMergedTemplateModel方法为新定义的抽象方法。
该抽象类有几个boolean属性exposeSessionAttributes,exposeRequestAttributes。 设置为true的话会将request和session中的键值和值丢入到renderMergedTemplateModel方法中的model这个Map参数中。
这个类是某些模板引擎视图类的父类。 比如FreemarkerView,VelocityView。
  • 7. ViewResolver接口

视图解释器,用来解析视图View,与View接口配合使用。
该接口只有1个方法,通过视图名称viewName和Locale对象得到View接口实现类:
  • 8. AbstractCachingViewResolver抽象类

带有缓存功能的ViewResolver接口基础实现抽象类,该类有个属性名为viewAccessCache的以 "viewName_locale" 为key, View接口为value的Map。
该抽象类实现的resolveViewName方法内部会调用createView方法,方法内部会调用loadView抽象方法。
  • 9. UrlBasedViewResolver类

继承自AbstractCachingViewResolver抽象类、并实现Ordered接口的类,是ViewResolver接口简单的实现类
AbstractCachingViewResolver
该类复写了createView方法:
createView
父类(AbstractCachingViewResolver)的createView方法内部会调用loadView抽象方法,UrlBasedViewResolver实现了这个抽象方法:
image
image

  
  
  
  
      
      *  
        
    
  
  
    
      
    
  
  
    
      testvalue
    
  

我们看到:以InternalResourceView这个JSP视图作为视图;viewNames我们设置了,这里的代表全部视图名(这个viewNames属性不设置也可以,代表全部视图名都处理);http响应头部contentType信息:text/html;charset=utf-8;attributesMap和attributes传入的Map和Properties参数都会被丢入到staticAttributes属性中,这个staticAttributes会被设置成AbstractView的staticAttributes属性,也就是request域中的参数。
image
image
image
我们看到request域中没有设置mytest和testvalue值。但是页面中会显示,因为我们配置了attributesMap和attributes参数。
如果我们把viewNames中的"*"改成"index1"。那么就报错了,因为处理视图名的时候index匹配不上index1。
image
  • 10. InternalResourceViewResolver类

继承自UrlBasedViewResolver,以InternalResourceView作为视图,若项目中存在“javax.servlet.jsp.jstl.core.Config”该类,那么会以JstlView作为视图。重写了buildView方法,主要就是为了给InternalResourceView视图设置属性
  • 11. ModelAndView对象

顾名思义,带有视图和Model属性的一个模型和视图类。
image
值得注意的是,这个视图属性是一个Object类型的数据,可以直接是View接口的实现类或者视图名(字符串)。

-------------------------------------------------------------------------------------------------------------------------------------------

下面我们来分析SpringMVC处理视图的源码。

SpringMVC在处理请求的时候,通过RequestMappingHandlerMapping得到HandlerExecutionChain,然后通过RequestMappingHandlerAdapter得到1个ModelAndView对象,之后通过processDispatchResult方法处理。processDispatchResult方法如下:
image
image
如果配置的ViewResolver如下:

  
  

那么就是使用InternalResourceViewResolver来解析视图。之前分析过,InternalResourceViewResolver重写了UrlBasedViewResolver的buildView方法。但是还是会调用UrlBasedViewResolver的buildView方法。

image
最终得到InternalResourceView或JstlView视图。这两个视图的render方法本文介绍重要接口及类的时候已分析。

特别参考[Format大佬的分享]http://www.cnblogs.com/fangjian0423/p/springMVC-view-viewResolver.html

你可能感兴趣的:(SpringMVC源码学习经历(识图解析器篇))