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

   <!-- 视图解析器 -->
    <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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,874评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,102评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,676评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,911评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,937评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,935评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,860评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,660评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,113评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,363评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,506评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,238评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,861评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,486评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,674评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,513评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,426评论 2 352

推荐阅读更多精彩内容