美文网首页后台工程师技术交流
SpringMVC源码学习经历(识图解析器篇)

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

作者: prisoner_mirror | 来源:发表于2019-02-28 18:12 被阅读4次

    (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(后文会讲到)。我们继续介绍其他类和接口

       <!-- 视图解析器 -->
        <bean id="viewResolver"
              class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <!-- 前缀 -->
            <property name="prefix">
                <value>/WEB-INF/</value>
            </property>
            <!-- 后缀 -->
            <property name="suffix">
                <value>.html</value>
            </property>
        </bean>
    
    • 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
    <bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
      <property name="prefix" value="/WEB-INF/view/"/>
      <property name="suffix" value=".jsp"/>
      <property name="viewClass" value="org.springframework.web.servlet.view.InternalResourceView"/>
      <property name="viewNames">
        <array>  
          <value type="java.lang.String">*</value>  
        </array>    
      </property>  
      <property name="contentType" value="text/html;charset=utf-8"/>
      <property name="attributesMap">
        <map>
          <entry key="mytest" value="mytestvalue"/>
        </map>
      </property>
      <property name="attributes">
        <props>
          <prop key="test">testvalue</prop>
        </props>
      </property>
    </bean>
    
    我们看到:以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如下:
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
      <property name="prefix" value="/WEB-INF/view/"/>
      <property name="suffix" value=".jsp"/>
    </bean>
    

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

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

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

    相关文章

      网友评论

        本文标题:SpringMVC源码学习经历(识图解析器篇)

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