5.1.3 处理请求的各组件(2)
![]() |
(点击查看大图)图5-1 DispatcherServlet组件发现算法 |
在初始化过程中DispatcherServlet会通过HandlerAdapter、HandlerMapping、HandlerExceptionResolver和ViewResolver类型寻求各种实现。然而,你可以将detect AllHandlerMappings,detectAllHandlerExceptionResolvers或detectAllViewResolvers的属性都设置成false,对HandlerAdapter以外的任何类型都停止该行为。要设置其中的一个或者多个属性,就得使用最初声明了DispatcherServlet的web.xml。代码清单5-2显示了关闭所有ViewResolver检测的例子。
注解
在该例写作时,尚无办法来关闭所有HandlerAdapter的自动检测。
代码清单5-2 关闭所有ViewResolver的检测
![]() |
假如真的关闭了自动发现,就得用默认的bean名称为每种类型至少命名一个bean。每种类型的默认bean名称参见表5-1。
DispatcherServlet对于这里的大多数接口都配置了默认的实现。这就意味着假如在ApplicationContext中找不到任何实现(不论通过名称还是类型),DispatcherServlet就会创建和使用以下实现:
![]() |
注意
MultipartResolver、HandlerExceptionResolver或ViewResolver没有默认实现。
现在让我们来更深入地了解一下处理管道中的每个元素,从HandlerAdapter接口开始。
2. HandlerAdapter
org.springframework.web.servlet.HandlerAdapter是系统级的接口,它允许在不同的请求处理器和DispatcherServlet间保持低耦合性。只要HandlerAdapter经过配置,DispatcherServlet就能与任何类型的请求处理器相互作用。
提示
假如应用程序仅包含Controller,那么可以忽视该部分。Controller是默认支持的且并不要求HandlerAdapter的明确配置。然而,如果有兴趣将第三方框架集成到Spring MVC话,请继续。
为什么不要求所有的请求处理器来实现一些众所周知的接口呢?DispatcherServlet是用来与任何类型的请求处理器相配合的,包括第三方框架。集成异构的软件包常常并不简单,因为源代码无法获得或很难改变。适配器设计模式试图通过适配第三方接口到客户的期望接口来解决这个问题。《设计模式》这本开创性的书将该模式的目标定义如下:"将一个类的接口转化成客户期望的另一个接口。适配器使本来因为接口不兼容而无法合作的多个类协同工作。"
Spring的HandlerAdapter通过委托获得该适配。代码清单5-3显示了HandlerAdapter接口。
代码清单5-3 HandlerAdapter接口
![]() |
DispatcherServlet会检查HandlerAdapter是否支持带有调用supports()的处理器类型。如果这样的话,DispatcherServlet就会要求适配器通过handle()方法将请求委托给处理器。注意该接口是如何不通过ApplicationContext的查找获得处理器的。
若应用程序仅使用Controller,像几乎所有的Spring MVC应用程序那样,那就永远见不到这个接口。该接口随同其默认子类SimpleControllerHandlerAdapter都是为框架内部使用的。然而,如果打算集成外来的Web框架,就可以使用该类将其集成到DispatcherServlet。
代码清单5-4是一个外来Web框架下HandlerAdapter实现的简单例子。
代码清单5-4 HandlerAdapter例子
![]() |
配置DispatcherServlet以使用HandlerAdapter极其简单,因为DispatcherServlet在默认状态下查看所有HandlerAdapter的ApplicationContext。它按类型找出所有适配器并对它们进行排序,对实现org.springframework.core.Ordered接口的适配器尤加关注。
代码清单5-5包含ExoticFrameworkHandlerAdapter的bean定义。
代码清单5-5 带ExoticFrameworkHandlerAdapter的ApplicationContext
![]() |
HandlerAdapter的名称是什么都没关系,因为DispatcherServlet会寻找HandlerAdapter类型的bean。
要注意,若指定了任何HandlerAdapter,默认的SimpleControllerHandlerAdapter就不再被使用。如果应用程序需要两个以上的HandlerAdapter,就得明确指定所有的HandlerAdapter,包括默认的。
小结
作为Adapter设计模式的一个例子,HandlerAdapter是促进DispatcherServlet和第三方框架简单集成的系统级接口。除非使用第三方框架,否则该接口及其实现一般就会对开发者隐藏。DispatcherServlet还会串连在ApplicationContext中的多个适配器,并同时根据Ordered接口对它们进行排序。