官方文档说明
前言:DispacherServlet是什么?
与很多的web框架一样,Spring Mvc也是围绕着一个中央Servlet展开的,Spring mvc 的这个servlet就是DispatcherServlet,但这个DispatcherServlet能做的更多。它与Spring IoC容器做到了无缝集成,这意味着,Spring提供的任何特性,在Spring MVC中你都可以使用。同时也说明了DispatcherServlet就是一个Servlet(它继承自HttpServlet基类),同样也需要在你web应用的web.xml配置文件下声明。你需要在web.xml文件中把你希望DispatcherServlet处理的请求映射到对应的URL上去。这就是标准的Java EE Servlet配置;下面的代码就展示了对DispatcherServlet和路径映射的声明:
<servlet>
<servlet-name>example</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>example</servlet-name>
<url-pattern>/example/*</url-pattern>
</servlet-mapping>
</web-app>
流程
- 1.那么从发送请求到DispatcherServlet之间做了什么呢?(也就是上图的第一步)
这里就是对请求的一个描述过程,http请求到了后台之后经历了一系列的servlet转发最后到达了doDispatch()这个方法;这个方法中做了如下几件事情:
- 2.第二步映射处理器又做了什么呢?
1). 获取处理执行链对象: HandlerExecutionChain mappedHandler = getHandler(processedRequest);
处理执行链类 HandlerExecutionChain : 由处理对象 handler 和 拦截器 HandlerInterceptor 组成。这里就涉及了一个新的概念HandlerInterceptor:
Spring的处理器映射机制包含了处理器拦截器。拦截器在你需要为特定类型的请求应用一些功能时可能很有用,比如,检查用户身份等。在这里可以配置拦截请求:文档链接如下:配置HandlerInterceptor拦截器。
2). 获取处理适配器: HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
SpringMVC 遍历所有的 HandlerAdapter 类,如果某个处理适配器支持该处理器类型,则返回该处理器。3). 调用拦截器的 preHandle 方法;
preHandle(..),它在处理器实际执行 之前 会被执行; postHandle(..),它在处理器执行 完毕 以后被执行; afterCompletion(..),它在 整个请求处理完成 之后被执行。这三个方法为各种类型的前处理和后处理需求提供了足够的灵活性。
preHandle(..)方法返回一个boolean值。你可以通过这个方法来决定是否继续执行处理链中的部件。当方法返回 true时,处理器链会继续执行;若方法返回 false, DispatcherServlet即认为拦截器自身已经完成了对请求的处理(比如说,已经渲染了一个合适的视图),那么其余的拦截器以及执行链中的其他处理器就不会再被执行了。4)调用具体的接口方法,并返回模型视图对象: mv = ha.handle(processedRequest, response,mappedHandler.getHandler());
这是一个很复杂的过程,调用具体方法是做了以下几个事情:
(a)解析参数:
springmvc解析参数的时候会先去方法定义的所有参数列表然后根据集体需要的参数类型调用相应的参数解析器,这一步是通过反射的相关内容完成的。
(b)根据参数调用具体的方法,并获取返回值:
交有具体的参数解析器后,完成具体的相应参数的解析,例如包括请求中得contentType是application/json等进行相应的解析。
(c)返回返回值:
解析完参数后,则通过反射机制调用具体的方法并获取返回值。5)调用拦截器的 postHandle 方法;
preHandle(..),它在处理器实际执行 之前 会被执行; postHandle(..),它在处理器执行 完毕 以后被执行;6)调用拦截器的afterCompletion(..),它在 整个请求处理完成 之后被执行。这三个方法为各种类型的前处理和后处理需求提供了足够的灵活性。
7)处理结果: processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
(a)处理异常;
如果在前面的处理中抛出了异常,则会获取相应的模型视图对象。有两种处理方式:如果异常对象为 ModelAndViewDefiningException 类型,则直接获取模型视图对象;否则的话调用当前系统内的处理异常解析器 ( HandlerExceptionResolver ) 处理:如果某个异常解析器返回了有效的模型视图对象,则跳出循环。
此处的 ExceptionHandlerExceptionResolver 类通过用户自定义的 @ExceptionHandler 方法解析异常,如果用户未定义,则跳出该解析器。
(b)渲染 ModelAndView 对象;
在渲染方法 render() 中,如果传入的 ModelAndView 对象是 View 引用类型,即为 String 字符串时,则调用当前的视图解析器 ViewResolver 解析该字符串,如当前配置了视图解析器为:
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".html"/>
</bean>
则该实现会在视图解析器列表 viewResolvers 中: 在解析时,将会添加上对应的 prefix, suffix, 接下来则调用 View 对象的 render() 方法,根据提供的 Model 对象渲染该视图对象。
(c)调用处理执行链的 triggerAfterCompletion() 方法。
该方法只调用在 preHandle() 方法中成功调用且返回为 true 的拦截器,且从列表后往前调用。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。