《Spring技术内幕》读书笔记——Spring MVC

1、根上下文初始化

DispatcherServlet分发请求,可以配置多个,定义了URL映射;ContextLoaderListener是Spring MVC的启动类,被定义为一个与Web服务生命周期相关的监听器,负责完成IOC容器在Web环境中的启动。DispatcherServlet和ContextLoaderListener提供了在Web容器中对Spring的接口,这些接口与容器的耦合通过ServletContext实现,ServletContext为Spring的IOC容器提供了宿主环境,在宿主环境中Spring MVC建立起一个IOC容器体系,通过ContextLoaderListener初始化。

IOC容器的启动过程就是建立(根)上下文的过程,根上下文和ContextLoaderListener相伴而生。还有一个上下文用来保存DispatcherServlet需要的MVC对象(DispatcherServlet的上下文,子上下文),是根上下文的子上下文。。在ContextLoader中,完成了两个IOC容器的建立,一个是建立起根上下文的双亲IOC容器,一个是建立WebApplicationContext(根上下文)。如下是ContextLoaderListener建立根上下文的过程。

在启动过程中,Spring默认使用XmlWebApplicationContext,loadBeanDefinitions时,调用reader.loadBeanDefinitions(configLocation),定义了getDefaultCofigLocations方法,默认从/WEB-INF/applicationContext.xml读取。然后通过XmlBeanDefinitionReader载入Bean信息,完成根上下文初始化。

下面来看看上面的时序图,ContextLoaderListener通过ContextLoader完成实际的初始化。如下,载入根上下文的双亲上下文(loadParentContext),初始化根上下文(createWebApplicationContext),并使用ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE作为key将根上下文存储在ServletContext中

如下是初始化根上下文(createWebApplicationContext)的过程,determineContextClass决定容器类型,通过设置CONTEXT_CLASS_PARAM参数来完成。默认使用XmlWebApplicationContext,defaultStrategies.getProperty,策略模式。

初始化根上下文之后,被存储到ServletContext中,DipatcherServlet初始化自己的上下文时,取出根上下文,并设置为DipatcherServlet自带上下文的双亲上下文。

 

2、DispatcherServlet初始化

DipatcherServlet选取BeanNameUrlHandlerMapping作为默认的HandlerMapping(映射处理器),除了不同的HandlerMapping,还定制了不同的Handler(Controller),实现handleRequest接口方法,返回ModelAndView。Spring MVC还提供了各种视图(JSP、freemarker、EXCEL、PDF),拦截器,国际化等。

DipatcherServlet会建立自己的上下文来持有Spring MVC的bean对象(无则去父容器查找),在建立自己的容器时,从ServletContext中得到根上下文作为双亲上下文,再对自己的上下文初始化,存入ServletContext

    

从上图看到,DipatcherServlet的作用主要有初始化和请求分发两部分,在initStrategies()里,DipatcherServlet对handlerMapping、ViewResolver等也进行了初始化;作为一个Servlet,Web容器调用doGet/doPost之后,调用DipatcherServlet的doService,最终调用doDispatch

作为Servlet,在Servlet的初始化时调用init()。DipatcherServlet初始化时,首先调用HttpServletBean的init(),继而调用自己的initServletBean()在初始化过程中,这个DipatcherServlet的上下文被设置为根上下文的子上下文,根上下文是和Web应用对应的上下文,DipatcherServlet持有的上下文是和Servlet对应的,在一个Web应用中,可以有多个Servlet。根上下文中的Bean被子上下文共享,DipatcherServlet持有的上下文(容器)建立起来之后,通过refresh方法初始化。

    

取得根上下文的过程是从ServletContext中取得ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE的值,然后建立DipatcherServlet的上下文,传入parent,利用反射实例化,设置双亲上下文、配置文件位置等,最终refresh

    

initWebApplicationContext方法中还调用了onRefresh这个方法触发了initStrategies,对MVC框架的各种元素初始化,LocalResolver、HandlerMapping、ViewResolver等。以HandlerMapping初始化为例,从IOC容器中读入配置(getBean),建立在IOC容器初始化的基础上,其他的初始化与之类似。

 

3、请求分发

初始化完成后,所有HandlerMappings都被加在了,被放在一个List中并被排序。以SimpleUrlHandlerMapping为例,定义了map来持有映射关系,HandlerMapping接口定义了HandlerExecutionChain getHandler (HttpServletRequest request)方法HandlerExecutionChain 持有Handler和List<HandlerInterceptor>

getHandler需要提前配置好一个反应映射关系的handlerMap,是一个LinkedHashMap,通过BeanPostProcessor完成。最终getHandler根据request从handlerMap中取,如果取不到,便利找到最匹配的Handler。

   

下面看看如何分发处理请求,doService最终调用doDispatch分发请求。handler的请求处理过程是典型的command模式。可能有多个handlerMapping,getHandler时需要遍历。调用handler获得ModelAndView之后,交给视图类,就可以进行视图名的转换、视图的渲染和展现。

    

 

doDispatch方法里,获得ModelAndView之后,还调用了render方法渲染视图。render先对视图名称进行解析,得到视图对象,再展示数据。取得视图调用getBean。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值