Spring MVC的HandlerMapping:从相亲角到灭霸响指的奇幻漂流

108 阅读3分钟

《Spring MVC的HandlerMapping:从相亲角到灭霸响指的奇幻漂流》


一、介绍:HandlerMapping是Spring MVC的"婚介所红娘"

想象一下,你走进一家高端婚介所(Spring MVC应用),门口站着一位笑容可掬的红娘(HandlerMapping)。
她会根据你的身高、学历、星座(请求URL、请求方法、请求头),快速匹配最合适的相亲对象(Controller处理器)。
如果匹配成功,她会给你对方的微信(HandlerExecutionChain);如果失败,她会优雅地说"下一个更乖"(返回404)。

官方定义:HandlerMapping负责建立HTTP请求与处理器(Handler)之间的映射关系,是Spring MVC路由系统的核心调度员。


二、用法:三大"红娘"就业指南

Spring MVC有三位性格迥异的红娘,各有绝活:

  1. BeanNameUrlHandlerMapping(传统派)
    特点:简单直接,把Bean名称当URL路径
    配置代码:

    <bean name="/order" class="com.example.OrderController"/>
    
  2. SimpleUrlHandlerMapping(配置派)
    特点:用Map集中管理URL映射,适合XML配置党
    配置代码:

    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
      <property name="mappings">
        <props>
          <prop key="/user">userController</prop>
          <prop key="/product/*">productController</prop>
        </props>
      </property>
    </bean>
    
  3. RequestMappingHandlerMapping(现代派)
    特点:支持注解驱动开发,@RequestMapping就是它的秘密武器
    示例代码:

    @RestController
    public class UserController {
        @GetMapping("/users/{id}")
        public User getUser(@PathVariable Long id) {
            // 实现代码
        }
    }
    

三、案例:当三国人物玩转HandlerMapping

场景:曹操、刘备、孙权要开发一个"三国API平台"

  1. 曹操的XML风格(SimpleUrlHandlerMapping)

    <!-- 官渡之战接口 -->
    <bean id="battleController" class="com.caocao.BattleController"/>
    
    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
      <property name="mappings">
        <props>
          <prop key="/battle/guandu">battleController</prop>
        </props>
      </property>
      <property name="order" value="1"/>
    </bean>
    
  2. 刘备的注解流(RequestMappingHandlerMapping)

    @RestController
    public class RiceController {
        @GetMapping("/rice/{count}")
        public String borrowRice(@PathVariable int count) {
            return "玄德借走" + count + "袋大米";
        }
    }
    
  3. 孙权的混合开发(BeanNameUrlHandlerMapping)

    @Component("/wuhou")
    public class WuHouController implements Controller {
        public ModelAndView handleRequest(...) {
            return new ModelAndView("wuhou", "msg", "生子当如孙仲谋");
        }
    }
    

四、原理:HandlerMapping的"吃鸡"匹配算法

当请求到达时,HandlerMapping们会开启一场"绝地求生":

  1. 扫描地图:遍历所有注册的HandlerMapping
  2. 装备选择:每个HandlerMapping检查自己是否能处理该请求
  3. 决赛圈对决:若有多个匹配,按order值排序(值越小优先级越高)
  4. 大吉大利:第一个匹配成功的返回HandlerExecutionChain


五、对比:传统派VS现代派的世纪Battle

维度BeanNameUrlSimpleUrlRequestMapping(注解派)
配置方式XML/注解XML注解
URL灵活性★★☆☆☆★★★☆☆★★★★★
REST支持不支持有限支持完全支持
方法粒度类级别类级别方法级别
适用场景老项目维护集中式配置现代Web开发

六、避坑指南:前辈们用头发换来的经验

  1. 路径冲突引发血案
    ❌ 错误示范:

    @GetMapping("/users")
    @GetMapping("/users/*")
    

    ✅ 正确姿势:
    更精确的路径优先,建议使用/users/{id}明确区分

  2. 顺序引发的灵异事件
    ❌ 现象:配置了注解映射但总是不生效
    ✅ 排查:检查是否有传统HandlerMapping的order值更高

  3. 静态资源404之谜
    ❌ 问题:访问图片返回Controller的报错
    ✅ 解决:确保DefaultServletHandlerConfigurer配置在前


七、最佳实践:Spring Boot时代的生存法则

  1. 拥抱注解驱动:90%场景用@RequestMapping全家桶就够了
  2. 模块化配置:不同业务模块用@RestController("/api/v1/orders")划分
  3. 巧妙处理静态资源
    @Configuration
    public class WebConfig implements WebMvcConfigurer {
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler("/static/**")
                   .addResourceLocations("classpath:/static/");
        }
    }
    

八、面试考点:BAT考官最爱问的三大哲学问题

  1. HandlerMapping的作用是什么?
    → 相当于HTTP请求的调度中心,负责找到对应的处理器

  2. 不同HandlerMapping的执行顺序如何确定?
    → 通过order属性,值越小优先级越高

  3. 为什么现在推荐用注解方式?
    → 支持方法级映射、RESTful风格、无需XML配置更简洁


九、总结:HandlerMapping的进阶之路

从XML配置到注解驱动,HandlerMapping的进化史就是Spring发展的缩影。记住:

  • 现代开发首选@RequestMapping
  • 遇到路径冲突先查order值
  • 静态资源处理要配置优先级
  • 理解原理才能优雅填坑

最后送大家一句编程哲学:"优秀的框架设计,应该像灭霸的响指——一个响指,万物归位" 🚀