这一章,我们将描述 Spring Web MVC 的各个组件,组件接口,以及各个组件之间如何协调通信,进而理解 Spring Web MVC 框架的基本工作原理。
3.1 组件以及组件的接口
Spring Web MVC 是由若干组件组成的,这些组件相互独立又相互协调工作共同完成 Spring Web MVC 工作流。每个组件都有清晰的接口定义,接口后面都有一个设计良好的类实现体系结构,清晰的抽象出公用的逻辑并且实现在通用的抽象类里,同时提供常用的具体实现类。 进而实现一个清晰的,高可扩展的,可插拔的 Web MVC 体系结构。
下面我们介绍这些典型的组件,组件的功能以及组件所定义的接口。
-
派遣器处理器 Servlet 对象 (Dispatcher Servlet)
派遣器处理器 Servlet 对象 (Dispatcher Servlet) 是 Spring Web MVC 中最核心组件,它是一个实现类而并不是一个接口。
从类的继承角度来看,派遣器处理器对象 (Dispatcher Servlet) 最终继承自 HttpServlet 对象。通过若干个抽象类的划分,是派遣器处理器对象 (Dispatcher Servlet) 的类体系接口清晰明了,任务分明,容易扩展,我们将在后续章节详细分析派遣器处理器对象 (Dispatcher Servlet) 的类体系接口。
初始化时, 它通过内部的 Spring Web 应用程序环境,找到相应的 Spring Web MVC 的各个组件,如果这些组件没有显式配置, Spring Web MVC 将会根据默认加载策略初始化各个模块的默认实现。
服务时,它通过一套注册的处理器映射对象 (HandlerMapping) 找到一个处理器对象 (Handler) ,然后,从一套注册的处理器适配器对象( HandlerAdapter )中找到一个支持这个处理器对象 (Handler) 的处理器适配器对象( HandlerAdapter),并且通过它把控制流转发给这个处理器对象 (Hanlder) ,处理器对象 (Handler) 结束业务逻辑的调用后把模型数据和逻辑视图传回派遣器处理器 Servlet 对象 (Dispatcher Servlet) 。
派遣器处理器 Servlet 对象 (Dispatcher Servlet) 再通过视图解析器对象 (ViewResolver) 得到真正的视图对象( View ),把控制权交给视图对象( View ),同事传入模型数据,视图对象( View )会按照一定的视图层定义展现这些数据到用户响应对象里。
下一小节中我们将对这个流程进行完整的描述,并且在下一章中详细的分析 Servlets 的类体系结构。
-
处理器映射对象 (HandlerMapping)
处理器映射对象 (HandlerMapping) 是用于映射一个请求对象 (Request) 到一个处理器对象 (Handler) 。一个 Spring Web MVC 实例可能会包含多个处理器映射对象 (HandlerMapping) 。按照处理器映射对象所在的顺序,第一个返回非空处理器执行链对象 (HandlerExecutionChain) 的处理器映射,会被当作为有效的处理器映射对象。处理器执行链对象(HandlerExecutionChain) 包含一个处理器对象 (Hanlder) 和一组能够应用在处理器对象 (Handler) 上的拦截器对象(Interceptor).
它的接口定义如下 ,
图表 3 ‑1
在这个接口中,通过输入一个 HTTP 请求对象 (HttpServletRequest) 给方法 (getHandler) ,这个方法就会输出一个处理器执行链对象 (HandlerExecutionChain) 。进而我们能够从处理器执行链对象 (HandlerExecutionChain) 得到一个处理器对象(Handler) 。
-
处理器适配器对象 (HandlerAdaptor)
处理器适配器 (HandlerAdaptor) 是用来转接一个控制流到一个指定类型的处理器对象( Handler )。一个类型的处理器对象( Handler )通常会对应一个处理器适配器对象 (HandlerAdaptor) 的一个实现。处理器适配器对象(HandlerAdaptor) 能够判断自己是否支持某个处理器对象( Hanlder )。如果一个处理器适配器对象 (HandlerAdaptor)支持这种类型的处理器 (Handler) ,那么这个处理器适配器对象 (HandlerAdaptor) 就可以使用这个处理器对象( handler)处理当前的这个 HTTP 请求。
然而,处理器对象 (Hanlder) 是一个通用的 Java 对象类型 , 这样做是允许 Spring Web MVC 可以任意的去集成其他框架的处理器对象 (handler), 只需要为这个需要支持的处理器对象 (Handler) 提供一个客户化的处理器适配器对象(HanlderAdaptor), 就可以在不改变任何上层派遣器 Servlet 对象 (DispatcherServlet) 代码以及下层控制器对象 (Controller)代码的前提下,实现任意集成。后来证明,基于注释的控制器,以及 Spring Web Flow 都是通过这样的适配器的实现来完成和 Spring Web MVC 工作流集成的,我们将在后面章节详细讨论。
它的接口定义如下 ,
图表 3 ‑2
在这个接口中,通过输入一个处理器对象( Handler )给 supports() 方法,这个方法就会返回是否支持这个处理器。通过传入一个 HttpServletRequese , HttpServletResponse 和一个 Hanlder 对象给 handle() 方法,这个方法就会就会传递控制权给处理器对象 (Handler) 。
当处理器对象( Handler )处理这个 HTTP 请求后返回数据模型和逻辑视图名称的组合对象,处理器适配器会把这个返回结果进而返回给派遣器 Servlet(DispatcherServlet) 。 getLastModified 方法是用来处理一个带有 lastModified 头信息的HTTP 请求的。不是所有的处理器适配器( HandlerAdapter )都需要支持这个方法的。我们将在下一章详细讨论它的实现。
-
处理器对象 - 控制器对象( Handler - Controller)
处理器对象( Handler )是用于处理业务逻辑的一个基本单元。它通过传入的 HTTP 请求对象 (HttpServletRequese) 来决定如何处理业务逻辑和执行哪些服务,执行服务后返回相应的模型数据和逻辑视图名。处理器对象 (Handler) 是一个通用的对象类型。控制流是由处理器适配器 (HandlerAdaptor) 传递给处理器的。所以,一个类型的处理器对象 (Hanlder)一定会对应一个支持的处理器适配器 (HandlerAdaptor) 。这样可以实现,处理器适配器( HandlerAdaptor )和处理器(Handler) 的任意插拔。
控制器是 Spring Web MVC 中最简单的一个处理器。这个处理器有清晰的接口定义,通常这个类型的处理器对象(Handler) 是通过一个简单控制处理适配器对象 (SimpleControllerHandlerAdapter) 来传递控制的。
它的接口定义如下 ,
图表 3 ‑3
在这个接口中,通过输入一个 HTTP 请求对象( HttpServletRequese )和 HTTP 响应对象 (HttpServletResponse) 给方法handleRequest() 方法,这个方法就会返回一个处理后的模型数据和逻辑视图名的组合对象。这个对象将通过处理器适配器 (HandlerAdapter) 进而返回给派遣器 Servlet(DispatcherServlet) 。
Spring Web MVC 之所以具有高可扩展性,在于处理器适配器( HandlerAdapter )和处理器 (Handler) 的设计。这样可以让任意的一个处理器对象插入到 Spring Web MVC 的体系结构中,是它具有无限的扩展性。一个例子就是自从 Spring 2.5新引进的注释方法处理器适配器对象 (AnnotationMethodHandlerAdapter) 和注释处理器。 Spring Web Flow 也是器Spring Web MVC 扩展的一个典型例子,我们讲在下面章节中详细讨论他们的实现。
-
视图解析器对象 (ViewResolver)
视图解析器对象 (ViewResolver) 是用于映射一个逻辑视图名称到一个真正的视图对象( View )。当控制器对象(Controller) 处理业务逻辑之后,通常会返回需要显示的数据模型对象和视图的逻辑名称,这样就需要一个支持的视图解析器对象 (ViewResolver) 解析出一个真正的视图对象 (View) ,然后传递控制流给这个视图对象。
它的接口定义如下 ,
图表 3 ‑4
在这个接口中,通过输入一个逻辑视图名称和本地对象 (Locale) 给 resolveViewName 方法,这个方法就会返回一个事实上的物理视图对象( View )。本地对象 (Locale) 可以用来查找本地化的资源或者资源包。
-
视图对象 (View)
View 是用来把模型数据通过某种显示方式反馈给客户,通常是通过执行 JSP 页面来完成的。也可以通过其他的更复杂的显示技术来完整这个展示过程,例如, JSTL 视图, Tiles 视图,报表视图和二进制文件视图等等。
它的接口定义如下 ,
图表 3 ‑5
在这个接口中,通过输入 HTTP 请求对象( HttpServletRequese ) , HTTP 响应对象 (HttpServletResponse) 和一个模型Map 对象,这个组件就会把模型 Map 通过一定的显示方式包含到客户的 HTTP 响应对象 (HttpServletResponse) ,这就是提供给用户请求的最终响应。 getContentType() 能够返回这个视图所支持的内容类型,例如, XML, JSON, text/html等等。
3.2 组件间的协调通信
图表 3 ‑6
众所周知,一个 HTTP 请求发送到 Web 容器, Web 容器就会封装一个 HTTP 请求对象 (HttpServletRequest) ,这个对象包含所有的 HTTP 请求信息,例如, HTTP 参数以及参数值, HTTP 请求头的各种元数据。同时, Web 容器会创建一个HTTP 响应对象( HttpServletResponse ),用以发送 HTTP 响应给客户端用户。然后, Web 容器传递 HTTP 请求对象(HttpServletRequest) 和 HTTP 响应对象( HttpServletResponse )给 Servlet 对象的 service() 方法。
实际上, Spring Web MVC 的入口就是一个客户化的 Servlet ,称为派遣器 Servlet 对象 (DispatcherServlet) 。这个派遣器Servlet 对象( DispatcherServlet )得到 HTTP 请求对象 (HttpServletRequest) 和 HTTP 响应对象( HttpServletResponse )后,一个典型的 Spring Web MVC 工作流就开始了。
派遣器 Servlet 对象( DispatcherServlet )首先查找所有注册的处理器映射器对象( HandlerMapping ),然后,遍历所有的处理器映射器对象( HandlerMapping ),直到一个处理器映射器对象( HandlerMapping )返回一个非空的处理器执行链对象 (HandlerExecutionChain) 。那么,处理器执行链对象 (HandlerExecutionChain) 就包含着一个需要处理当前 HTTP 请求的一个处理器对象( Handler )。如图表 3-6 第 1 步。
这里,一个处理器对象 (Handler) 被设计成了一个通用的对象类型,所以,这里需要一个处理器适配器( HandlerAdaptor )去派遣这个控制流到一个处理器对象 (Handler) ,因为只有支持这种类型的处理器( Handler )的处理器适配器(HandlerAdapter) 才知道如何去传递控制流给这个类型的处理器( Hanlder )。
拿到了处理器对象 (Hanlder) 以后,派遣器 Servlet 对象( DispatcherServlet )则查找所有注册的处理器适配器对象(HandlerAdapter ),然后,遍历所有的处理器适配器对象( HandlerAdapter )查询是否有一个处理器适配器对象(HandlerAdapter )支持这个处理器对象( Handler )。如图表 3-6 第 2 步。
如果有这样的一个处理器适配器对象 (HandlerAdapter) ,则派遣器 Servlet 对象( DispatcherServlet )将控制权转交给这个派遣器适配器对象 (HandlerAdapter) 。如图表 3-6 第 3 步。派遣器适配器对象( HandlerAdapter )和真正的处理器对象(Handler) 是成对出现的,所以,这个支持的处理器适配器对象( HandlerAdapter )则知道如何去使用这个处理器 (Handler)去处理这个请求。最简单的一个处理器则是控制器对象( Controller )。处理器适配器对象 (HandlerAdapter) 将传递 HTTP请求对象( HttpServletRequest )和 HTTP 响应对象( HttpServletResponse )给控制器,并且期待控制器返回模型和视图对象( ModelAndView )。如图表 3-6 第 3.1 步。这个模型和视图对象( ModelAndView )对象包含着一组模型数据和视图逻辑名称,并且最终返回给派遣器 Servlet 对象( DispatcherServlet ) .
派遣器 Servlet 对象( DispatcherServlet )然后查找所有注册的视图解析器对象,并且遍历所有的视图解析器对象(ViewResolver ),直到一个视图解析器对象( ViewResolver )返回一个物理的视图对象( View )。如图表 3-6 第 4 步。
最后,派遣器 Servlet ( DispatcherServlet )把得到的一组模型数据传递给得到的物理视图对象( View )。如图表 3-6 第 5步。然后,视图对象则会使用响应的表现层技术,把模型数据展现成 UI 界面,并且通过 HTTP 响应对象(HttpServletResponse )发送给 HTTP 客户。
3.3 本章小结
这一章,我们介绍了 Web MVC 在 Spring 中是如何实现的。具体分析了 Spring Web MVC 架构中的各个组件,组件的功能,以及组件的接口。最后,大体的分析了 Spring Web MVC 的工作流是如何传递和工作的。
下一章,我们将深入抛析 Spring Web MVC 的架构的具体实现。
http://blog.csdn.net/robertleepeak/article/details/5890660