浅析不同的 HandlerMapping 以及 HandlerAdapter 之间的作用以及区别

AUTHOR | nicechi
类别 | Spring
发表 | 2019-09-10 10:55:49
更新 | 2020-08-05 21:30:06

HandlerMapping 与 HandlerAdapter

HandlerMapping 和 HandlerAdapter 都是 interface ,DefaultAnnotationHandlerMapping 和 RequestMappingHandlerMapping 为 HandlerMapping 的实现类,AnnotationMethodHandlerAdapter 和 RequestMappingHandlerAdapter 为 HandlerAdapter 的实现类。

简要来说,HandlerMapping 所起的作用就是将 handler method(即使用了 @RequestMapping ,或 @GetMapping 或 PostMapping 注释的方法)映射到指定的 URL 上。

HandlerAdapter 是用来调用使用了 @RequestMapping (或者 @GetMapping ,@PostMapping 等注解)注解的方法。因为 DispatcherServlet 作为一个 Front Controller (前端控制器),会接收所有的 request,并且将 request 转发给相对应的 Controller ,然后调用符合要求的 handler method 来进行业务处理。但是  DispatcherServlet 无法直接调用 handler method,这时候就需要通过 HandlerAdapter 的帮助来调用符合要求的 handler method。

所以说,HandlerMapping 和 HandlerAdapter 是相互配合工作的,HandlerMapping 用来映射,HandlerAdapter 用来调用所映射到的 handler method,两者各司其职,缺一不可。

所以在没有声明相关的 HandlerMapping 或 HandlerAdapter 的 Web Spring Application 中,@RequestMapping 等的注解将不起作用。

DefaultAnnotationHandlerMapping 与 AnnotationMethodHandlerAdapter 

DefaultAnnotationHandlerMappingAnnotationMethodHandlerAdapter 分别为 HandlerMapping 和 HandlerAdapter 的实现类。

总的来说, DefaultAnnotationHandlerMapping 和 AnnotationMethodHandlerAdapter 分别帮助 Spring MVC(或者说 DispatcherServlet)将所接收的 request 转发给相对应的 controller,并调用相关的 handler method 来完成业务处理。

注意:DefaultAnnotationHandlerMapping 和 AnnotationMethodHandlerAdapter 从 Spring 3.2 开始就已经被标注为 deprecated ,取而代之的是 RequestMappingHandlerMapping 和 RequestMappingHandlerAdapter。

RequestMappingHandlerMapping 和 RequestMappingHandlerAdapter 

RequestMappingHandlerMappingRequestMappingHandlerAdapter 在 Spring 3.1 的时候出现,并在 Spring 3.2 中正式代替了 DefaultAnnotationHandlerMapping 和 AnnotationMethodHandlerAdapter。其作用与 DefaultAnnotationHandlerMapping 和 AnnotationMethodHandlerAdapter 相差无几。

RequestMappingHandlerMapping 通过创建 RequestMappingInfo 实例来维护 URL 与 handler 之间的关系

之所以要让 RequestMappingHandlerMapping 和 RequestMappingHandlerAdapter 代替 DefaultAnnotationHandlerMapping 和 AnnotationMethodHandlerAdapter ,Spring Doc 给出的理由简要归结起来有两点:

  1. RequestMappingHandlerMapping 和 RequestMappingHandlerAdapter 更加灵活,能够更好地去定制或扩展
  2. RequestMappingHandlerMapping 和 RequestMappingHandlerAdapter 使用了 HandlerMethod 的概念

启用 HandlerMapping 与 HandlerAdapter

在配置类中声明

//在 Java 中注册 DefaultAnnotationHandlerMapping 和 AnnotationMethodHandlerAdapter 
@Configuration
public class DispatcherServletConfig {

    @Bean
    public DefaultAnnotationHandlerMapping defaultAnnotationHandlerMapping(){
        return new DefaultAnnotationHandlerMapping();
    }

    @Bean
    public AnnotationMethodHandlerAdapter annotationMethodHandlerAdapter(){
        return new AnnotationMethodHandlerAdapter();
    }

}

//在 Java 中注册 RequestMappingHandlerMapping 和 RequestMappingHandlerAdapter
@Configuration
public class DispatcherServletConfig {

    @Bean
    public RequestMappingHandlerMapping requestMappingHandlerMapping(){
        return new RequestMappingHandlerMapping();
    }

    @Bean
    public RequestMappingHandlerAdapter requestMappingHandlerAdapter(){
        return new RequestMappingHandlerAdapter();
    }

}

在 xml 中声明

<beans ...>
    <bean
      class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>
    <bean
      class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
</beans>

或者 
<beans ...>
    <bean
      class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
     
    <bean
      class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
</beans>

通过 <mvc:annotation-driven/>

  • 对于 Spring 3.1 及之前的版本, <mvc:annotation-driven /> 将会自动注册 DefaultAnnotationHandlerMapping 和 AnnotationMethodHandlerAdapter 这两个 bean(因为此时这两个 bean 还没有被遗弃)
  • 对于 Spring 3.1 之后的版本,<mvc:annotation-driven /> 将会自动注册 RequestMappingHandlerMapping 和 RequestMappingHandlerAdapter 这两个 bean(因为此时这两个 bean 已经用来代替 DefaultAnnotationHandlerMapping 和 AnnotationMethodHandlerAdapter 了)
<beans ...>

    ...

    <mvc:annotation-driven />
    ...

</beans>

通过 @EnableWebMvc 

从 Spring 3.1 开始,可以使用 @EnableWebMvc(通常与 @Configuration 注解用在一起) 来自动注册 RequestMappingHandlerMapping 和 RequestMappingHandlerAdapter 

@Configuration
@EnableWebMvc
public class DispatcherServletConfig {

   ...

}

 

最后,希望这篇文章能带给你点启发,Have Fun!

 


CATEGORY

TOP