Spring MVC:DispatcherServlet

在 Spring MVC 中,有一个类是必定要去了解和熟悉的,这个类就是 DispatcherServlet,该类负责了 MVC 中最主要的内容——请求转发处理。 在本文中,我们会在源码级别讲述 DispatcherServlet 的运行机制和高度灵活的扩展性。

DispatcherServlet 的处理过程

DispatcherServlet 的处理过程更像是一个循环执行接口程序的过程,只是有几个相对独立的部分。如果使用 IDE 进行断点你会发现它的流程如下:
  1. doService
    1. 解析请求属性
  2. doDispatch
    1. getHandler( 请求到 Handler 对象映射 )
    2. getHanderAdapter
    3. preHandle
    4. handle
    5. postHandle
    6. processDispatchResult
      1. 完成异常解析
      2. render
        1. 区域处理
        2. 视图名解析
        3. 视图呈现
    7. afterCompletion

DispatcherServlet 的功能

DispatcherServlet 运行过程有以下几个大的功能板块:
  • 基于 JavaBeans 的方式进行配置
  • 控制 Handler 对象路由:HandlerMapping
  • Handler 适配处理:HandlerAdapter
  • 异常处理策略
  • 视图解析策略
  • 请求视图名转译
  • 复合表单内容处理
  • 区域解析
  • 主题解析
Java Beans 方式配置是 Java EE 中的一个规范,其定义 Java Beans 支持属性,事件和方法。如果你对 Java Beans 还不够熟悉可以查看 Oracle 对 Java Beans 是怎样编写的来了解具体的信息
HandlerMapping 负责了请求的路由,也就是说在接收到请求后,请求会经过它的处理最后返回 Handler 对象(可以是任意的类型)。其运行机制由两个组件组成:HandlerInterceptor 和 HandlerExecutionChain。HandlerInterceptor 有三个主要方法:preHandle(),postHandle(),afterCompletion()。
  • preHandle() 方法在 HandlerAdapter 发起调用 Handler 时触发。如果返回 true 表示会处理下一个 Interceptor,否则会认为以及处理完请求。
  • postHandle() 方法在 HandlerAdapter 调用 Handler 并且在 呈现视图 之前调用
  • afterCompletion() 仅在 preHandle() 方法返回 true 并且呈现视图之后执行
HandlerExcutionChain 类真正地组织 HandlerInterceptor 和 Handler 对象。并且真正在调用preHandle(),postHandle(),afterCompletion()。最后这个对象在 HandlerMapping 中 getHandler() 进行返回。
HandlerAdapter (适配器模式)负责完成 Handler 的实际处理。在 HandlerMapping 的处理结果的基础上,HandlerAdapter 表达了如何运作 Handler 对象,如 SimpleControllerHandlerAdapter 是针对 Controller 接口调用 Handler 对象的 handleRequest() 方法完成处理的。
异常处理由 HandlerExceptionResolver 负责,在流程 3-7 步中,如果抛出了异常会经由 processDispatchResult() 进行判断最后交由 processHandlerException() 进行检查异常解析结果,循环判断(最后一个
HandlerExceptionResolver 为第一个判断)有一个可以处理(判断 ModelAndView 返回值不为空)那么就会认为处理完成并把 ModelAndVIew 进行返回,间接使用 视图解析 的执行路径 。
视图解析,由 ViewResolver 负责,ViewResolver 会通过 viewName 获取到相应的 View 对象最后完成 ModelAndView 的呈现工作。与上面的做法先类似,都是使用循环的方式进行解析,一旦解析成功直接返回。 processDispatchResult() 负责调用 render() 方法呈现相应的页面结果。在 render() 方法中,地区解析是在这里完成的,它可以使用 Accept-Language 请求头来给 response 对象设置区域(Content-Language)响应头。最后通过 resolveViewName 获取到交由 View 对象进行实际的呈现工作。
请求视图名转译,通过请求获取相应的视图名,最后经过 ViewResolver 解析出相应的 View 对象,默认的转译类(DefaultRequestToViewNameTranslator)是把请求路径和资源名返回,如 http://localhost/a/b/c.html 将会返回 a/b/c

DispatchServlet 应用

  1. 自定义 HandlerIntercepter ,可以完成与 Handler 进行绑定的拦截处理,而不需要 AOP 编程
  2. 自定义 HandlerAdapter,可以实现自定义的 Handler 如实现一套不同的控制器处理逻辑
  3. 自定义 ViewResovler 视图解析,实现定制的 视图 呈现方式
  4. 自定义 HandlerExceptionResolver 异常处理,

发布者

codimiracle

nothing want to say.

发表评论

电子邮件地址不会被公开。 必填项已用*标注