web.xml中的ContextLoaderListener与项目的启动相关,那DispatcherServlet又有什么作用呢?
web.xml文件有这段配置
作用
DispatcherServlet是一个前端控制器,所以的web请求都经过它来处理,进行转发、匹配、数据处理后,并转由页面进行展现。
DispatcherServlet主要用作职责调度工作,本身主要用于控制流程,主要职责如下:
1、文件上传解析,如果请求类型是multipart将通过MultipartResolver进行文件上传解析;
2、通过HandlerMapping,将请求映射到处理器(返回一个HandlerExecutionChain,它包括一个处理器、多个HandlerInterceptor拦截器);
3、通过HandlerAdapter支持多种类型的处理器(HandlerExecutionChain中的处理器);
4、通过ViewResolver解析逻辑视图名到具体视图实现;
5、本地化解析;
6、渲染具体的视图等;
7、如果执行过程中遇到异常将交给HandlerExceptionResolver来解析。
DispatcherServlet的启动和初始化
- HttpServletBean
主要做一些初始化的工作,将web.xml中配置的参数设置到Servlet中。比如servlet标签的子标签init-param标签中配置的参数。 - FrameworkServlet
将Servlet与Spring容器上下文关联。其实也就是初始化FrameworkServlet的属性webApplicationContext,这个属性代表SpringMVC上下文,它有个父类上下文,既web.xml中配置的ContextLoaderListener监听器初始化的容器上下文。 - DispatcherServlet
初始化各个功能的实现类。比如异常处理、视图处理、请求映射处理等。
在Web容器启动时将调用Servlet的init方法进行初始化。
HttpServletBean中初始化方法
下面看一下FrameworkServlet的initServletBean()方法
由上面MVC上下文的建立的过程可知,根上下文DispatcherServlet的上下文的双亲上下文,因此根上下文中管理的Bean也可以被DispatcherServlet的上下文使用。
下面我们看一下DispatcherServlet的上下文的创建过程:
DispatcherServlet继承FrameworkServlet,并实现了onRefresh()方法提供一些前端控制器相关的配置:
下面我们详细分析一下HandlerMappings的初始化过程,HandlerMappings完成了对MVC中Controller的定义和配置,在web应用中,这些控制器是与具体的HTTP请求对应的。
经过以上过程,handerMappings变量已经获取了在BeanDefinition中配置好的映射关系。
HTTP请求的分发
上节初始化完成时,handerMappings都已被加载,这些handerMappings都会放在一个List中并排序,存储着HTTP请求对应的映射数据。一般每一个handlerMapping可以持有一系列从URL请求到Controller的映射,而SpringMVC提供了一系列的HandlerMapping实现。
HandlerMapping的配置
HandlerMapping接口封装了映射关系,并定义了getHandler方法
HandlerExecutionChain中持有一个Interceptor链和一个handler对象,这个handler对象实际上就是HTTP请求对应的Controller。
父类AbstractHandlerMapping继承了WebApplicationObjectSupport,所以SimpleUrlHandlerMapping可以通过覆写initApplicationContext注册Handler.
注册Handler前,不忘靠AbstractHandlerMapping来初始化拦截器.
// SimpleUrlHandlerMapping
|
|
AbstractUrlHandlerMapping中的registerHandler方法
handlerMap中保存了URL和Controller的映射关系,为HTTP请求准备好了基本的映射数据,根据这个handlerMap中的映射数据,可以由URL请求得到对应的handler.
AbstractHandlerMapping实现了HandlerMapping的getHandler方法
上面的代码是controller与URL的映射关系,下面我们看一下method与url的映射关系:
由于AbstractHandlerMethodMapping实现了InitializingBean接口,因此Bean初始化时会调用afterPropertiesSet方法:
请求的分发
DispatcherServlet是HttpServlet的子类,在MVC框架完成初始化后,通过doService()来相应HTTP的请求。
DispatcherServlet的doService()代码如下:
具体的处理是在doDispatch()中完成的:
下面看一下在DispatcherServlet是如何根据初始化时得到的映射关系获取HandlerExecutionChain
|
|
得到Handler的具体过程在getHandlerInternal方法中实现,从HTTP请求中得到URL,并根据URL到urlMapping中获得handler
|
|
得到HandlerExecutionChain后,DispactherServlet通过HandlerAdapter对这个Handler的合法性进行判断,返回适配结果。