Spring MVC源码分析--视图解析过程
写在最前,本文中的源码是4.2.3版本的源码,针对的是JstlView,解析JSP,HTML视图的处理器是InternalResourceViewResolver。
视图解析的过程即DispatcherServlet的doDispatch()方法的调用的processDispatchResult();
本文中涉及到的部分类之间的关系:
JstlView继承InternalResourceView,InternalResourceView继承AbstractUrlBasedView,AbstractUrlBasedView继承AbstractView,AbstractView实现View;
InternalResourceViewResolver继承UrlBasedViewResolver,UrlBasedViewResolver继承AbstractCachingViewResolver,AbstractCachingViewResolver实现ViewResolver;
详细过程(这里只描述核心方法,其他方法会掠过,且不会再说明,就是描述中可能出现:“方法调用完,然后调用下一个方法”,可能这两个方法之间有调用其它的方法,但是因为这个/这些方法不是核心方法,所以不会被提及):
1,DispatchServlet的processDispatchResult()里,调用DispatchServlet的render()方法;
2,DispatchServlet的render()方法里,调用DispatchServlet的resolveViewName()方法,在配置文件里注册的全部ViewResolver对象中,寻找合适的ViewResolver对象;
3,DispatchServlet的resolveViewName()方法里,因为配置文件中注册的是InternalResourceViewResolver,调用InternalResourceViewResolver的resolveViewName()方法(AbstractCachingViewResolver的);
4,InternalResourceViewResolver(AbstractCachingViewResolver的)的resolveViewName()方法里,调用InternalResourceViewResolver的createView()方法(AbstractCachingViewResolver的);
5,InternalResourceViewResolver的createView()方法(AbstractCachingViewResolver的)里,调用InternalResourceViewResolver的createView()方法(UrlBasedViewResolver的);
6,InternalResourceViewResolver的createView()方法(UrlBasedViewResolver的)里,调用InternalResourceViewResolver的buildView()方法(UrlBasedViewResolver的),buildView()方法里,初始化了一个View对象,该对象是一个AbstractUrlBasedView,该View对象的类型是配置文件中对应ViewResolver对应的viewClass,配置文件中是JstlView,那么这个View对象也就是JstlView类型的,把配置文件里面的前缀拼接viewName再拼接后缀所获得的字符串这个对象里面的成员属性url,设置是否暴露PathVariable,设置requestContext,设置staticAttributes,设置是否把全部Spring Bean暴露到request范围中(整个过程都没暴露,无意义),设置是否暴露contextBeanNames(整个过程都没暴露,无意义),;
7,InternalResourceViewResolver的resolveViewName()方法(AbstractCachingViewResolver的)返回一个View对象,然后DispatchServlet的resolveViewName()方法返回一个View对象,继续执行DispatchServlet的render()方法(当然,如果配置文件中没有配置ViewResolver,或者没有与viewName对应的视图,就不会返回一个View对象,而是返回null);
8,DispatchServlet的render()方法里,调用View对象的render()方法;
9,View对象的render()方法(AbstractView的)里,调用View对象的createMergedOutputModel()方法(AbstractView的),这个方法的执行过程是把View对象里面的 staticAttributes,ModelInternal,PathVariable(可选)和requestContext全都放在 mergedModel里面(注意,merge的顺序,staticAttributes-->pathVars-->model,pathVars会覆盖同名的staticAttribute),调用完createMergedOutputModel()方法,调用的View对象renderMergedOutputModel() 方法(InternalResourceView的),该方法里面会调用View对象的exposeModelAsRequestAttributes()方法,把mergedModel里的全部attribute作为request attribute暴露到request范围里,然后请求派遣到View的成员属性url去,整个过程结束,生下来的就是Web服务器把JSP编译成Servlet(如果是第一次被请求),执行该Servlet;
总的来说,过程如下:
处理viewName,通过配置文件中注册的viewResolver进行处理,通过调用该viewResolver的resolveViewName()方法,创建一个View对象,设置其url,设置其staticAttributes(静态属性,view实例配置中可配置,全部view都有同样的静态属性,现在不确定在哪里设置静态属性),设置requestContextAtribute,设置pathVariables(可选),设置是否把全部Spring Bean暴露到request范围中(整个过程都没暴露,无意义),设置是否暴露contextBeanNames(整个过程都没暴露,无意义),然后开始渲染视图,通过调用view对象的render()方法,把mv里的modelInternal,view里面的pathVariable,view里面的requestContextAtribute,view里面的staticAttributes暴露到request范围,然后请求派遣到View的成员属性url去,整个过程结束,剩下来的就是Web服务器把JSP编译成Servlet(如果是第一次被请求),执行该Servlet;
浙公网安备 33010602011771号