Spring MVC HandlerMapping 的职责是什么? 它是如何找到处理请求的 Controller 方法的?有哪些常见的 HandlerMapping 实现?

我们来详细了解一下 HandlerMapping 在 Spring MVC 中的角色和工作机制。

一、 HandlerMapping 的核心职责

HandlerMapping 的核心职责是根据传入的 HTTP 请求信息,查找并确定应该由哪个处理器(Handler)来处理这个请求

具体来说,它负责:

  1. 请求映射 (Request Mapping): 检查请求的各种属性,如 URL 路径、HTTP 方法 (GET, POST 等)、请求参数、请求头 (Headers)、媒体类型 (Content-Type, Accept) 等。
  2. 处理器查找 (Handler Lookup): 在应用程序中所有已注册的潜在处理器(通常是 Controller 类中的方法)中,根据预定义的映射规则(例如 @RequestMapping 注解中的配置),找到与当前请求最匹配的那一个处理器。
  3. 返回处理器执行链 (HandlerExecutionChain): 如果找到了匹配的处理器,HandlerMapping 不仅仅返回处理器本身,还会将其与应用于该处理器的拦截器 (HandlerInterceptor) 封装在一起,形成一个 HandlerExecutionChain 对象,然后将这个对象返回给 DispatcherServlet。拦截器链包含了处理器执行前后需要执行的通用逻辑。
  4. 处理无匹配处理器的情况: 如果根据请求信息找不到任何匹配的处理器,HandlerMapping 会通知 DispatcherServlet(通常是返回 null),DispatcherServlet 随后会决定如何处理(例如返回 404 Not Found)。

可以把 HandlerMapping 想象成应用程序的“路由表”查询服务。 DispatcherServlet 拿着一个请求过来问:“嘿,这个请求该交给谁处理?” HandlerMapping 就负责查表并告诉 DispatcherServlet:“这个请求应该由 X Controller 的 Y 方法处理,并且在处理前后需要经过 A、B 这两个拦截器。”

二、 HandlerMapping 如何找到处理请求的 Controller 方法?

HandlerMapping 查找 Controller 方法的过程取决于其具体的实现类。以最常用的 RequestMappingHandlerMapping(处理 @RequestMapping 及其变体注解)为例,其大致工作流程如下:

  1. 初始化阶段 (应用启动时):

    • RequestMappingHandlerMapping 会扫描 Spring 应用上下文中所有标记了 @Controller@RestController 注解的 Bean。
    • 对于每个找到的 Controller Bean,它会进一步检查其中所有标记了 @RequestMapping (或 @GetMapping, @PostMapping 等) 注解的方法。
    • 对每个标记了注解的方法,它会解析注解中定义的映射信息(URL 路径模式、HTTP 方法、参数条件、头条件、 consumes/produces 媒体类型等)。
    • 将这些映射信息与对应的 HandlerMethod 对象(包含了 Controller Bean 实例和具体的方法引用)关联起来,并存储在一个内部的数据结构中(可以想象成一个高效的查找表或注册表,例如使用 Map 或更复杂的树状结构来优化路径匹配)。这个过程建立了请求模式和处理方法之间的映射关系。
  2. 请求处理阶段 (运行时):

    • DispatcherServlet 调用 HandlerMappinggetHandler() 方法,并传入当前的 HttpServletRequest 时:
    • RequestMappingHandlerMapping 会从请求中提取关键信息,主要是 URL 路径HTTP 方法
    • 它使用请求的 URL 路径去匹配初始化阶段构建的映射注册表中存储的路径模式。这可能涉及到 Ant 风格的路径匹配(如 /users/*, /products/**/details)或更复杂的 URI 模板变量匹配(如 /users/{userId})。
    • 找到路径匹配的候选 Handler 后,它会进一步检查其他映射条件是否也满足,例如:
      • 请求的 HTTP 方法 是否与注解中指定的 method 属性匹配?
      • 请求中是否包含注解中 params 属性指定的请求参数
      • 请求头是否包含注解中 headers 属性指定的请求头
      • 请求的 Content-Type 是否与注解中 consumes 属性指定的媒体类型匹配?
      • 请求的 Accept 头是否与注解中 produces 属性指定的媒体类型匹配?
    • 它会选择最佳匹配的那个 HandlerMethod。Spring MVC 有一套复杂的匹配规则来处理多个 Handler 都可能匹配同一个请求的情况(例如,更具体的路径模式优先于更通用的模式)。
    • 一旦确定了最终的 HandlerMethodRequestMappingHandlerMapping 还会查找适用于该 Handler 的拦截器(这些拦截器通常是全局配置或针对特定路径模式配置的)。
    • 最后,将找到的 HandlerMethod 和适用的拦截器列表封装成 HandlerExecutionChain 返回给 DispatcherServlet

三、 常见的 HandlerMapping 实现

Spring MVC 提供了多种 HandlerMapping 实现,以支持不同的处理器定义和映射方式。以下是一些常见的实现(Spring Boot 通常会根据项目依赖和配置自动注册):

  1. RequestMappingHandlerMapping (最常用):

    • 作用: 处理标记了 @RequestMapping (及其快捷方式 @GetMapping, @PostMapping 等) 注解的 Controller 方法。
    • 特点: 目前Spring MVC 应用中最常用的是 HandlerMapping。它提供了非常灵活和强大的映射功能,支持 URI 模板、Ant 路径匹配、多种请求条件(方法、参数、头、媒体类型)等。
  2. BeanNameUrlHandlerMapping:

    • 作用: 将请求的 URL 路径与 Spring 容器中定义的 Bean 的名称 进行匹配。
    • 特点: 如果一个请求的 URL 是 /myController,这个 HandlerMapping 会查找容器中名为 /myController 的 Bean 作为 Handler。这是一种比较早期且相对简单的映射方式,现在不太常用。
  3. SimpleUrlHandlerMapping:

    • 作用: 允许我们通过显式的配置(通常在 Spring 的 XML 或 Java 配置类中)来维护 URL 模式和 Handler Bean 之间的映射关系。
    • 特点: 提供了比 BeanNameUrlHandlerMapping 更灵活的配置方式,可以将任意 URL 模式映射到任意 Handler Bean,并且可以方便地为特定 URL 模式配置拦截器。常用于映射一些非注解驱动的 Handler 或框架自带的 Handler(如处理静态资源的 ResourceHttpRequestHandler)。
  4. WelcomePageHandlerMapping (Spring Boot 特有):

    • 作用: 用于处理根路径 (/) 请求,并尝试查找并映射到静态欢迎页面(如 index.html)。
  5. HandlerMapping for Functional Endpoints (Spring WebFlux & Spring MVC):

    • 作用: 支持 Spring 5 引入的函数式 Web 框架风格,处理通过 RouterFunction 定义的路由规则。RouterFunctionMapping 是其实现类。

在Spring Boot Web 应用中,RequestMappingHandlerMapping 会被自动配置并作为主要的 HandlerMapping。如果我们定义了静态资源处理或使用了 Actuator 端点,SimpleUrlHandlerMapping 也可能被自动配置用于处理这些特定的 URL 模式。

在开发中我们不需要直接与 HandlerMapping 实现交互,只需要通过注解(如 @RequestMapping)或配置(如定义 RouterFunction Bean)来声明映射规则即可。DispatcherServlet 会自动使用注册的 HandlerMapping 来完成查找工作。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰糖心书房

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值