浅析Spring Boot请求映射原理

本文探讨Spring Boot中DispatcherServlet的自动装配过程,详细分析请求映射的关键步骤,包括doDispatch方法、getHandler方法及AbstractHandlerMapping的getHandlerInternal方法。通过源码解析,阐述了如何从请求到找到合适的处理器方法的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

浅析Spring Boot请求映射原理

Spring Boot的底层还是Spring MVC,那么Spring Boot的请求映射就与Spring MVC是相同的,那就是根据DispatcherServlet完成了请求映射的功能。但是我们没有手动去配置DispatcherServlet对应的配置项,那么Spring Boot是如何加载的DispatcherServlet呢,这个答案就是之前讲解的Spring Boot自动装配。

那么首先来看看自动装配的DispatcherServlet

测试程序

@RestController
@RequestMapping("/user")
public class UserController {
   
   
    
    @GetMapping("/hello")
    public String hello() {
   
   
        return "hello world!";
    }

}

加载DispatcherServlet

之前分析Spring Boot自动装配原理时可以发现,Spring Boot是通过扫描所有引入的jar包中的spring.factories文件来获取自动配置项的,那么DispatcherServlet的自动配置也会通过这种方法引入。我们可以在spring-boot-autoconfigure-2.3.4.RELEASE.jar包下的META-INF/spring.factories中找到这个自动配置类:DispatcherServletAutoConfiguration。

image-20210502194235789

在这个自动配置类中,会判断当前应用是否为SERVLET类型的web应用,是的话才会继续导入DispatcherServlet。

image-20210502194532294

当满足上述的条件后,还会再进行其他的判断:

image-20210502195229585

只有DefaultDispatcherServletCondition和ServletRegistration(接口)这两个类存在时才会加载DispatcherServlet,并且通过WebMvcProperties为DispatcherServlet绑定了相应的配置项:

image-20210502195436495

可以看出这个配置是以spring.mvc作为前缀的配置,那么它都包含哪些配置呢:

image-20210502195544975

通过WebMvcProperties类或者application.yml文件我们可以发现它的可配置项极多,这些配置项的作用不是请求映射的关键,这里不再展开讲解。

当满足这一切条件之后,spring boot会为我们new一个dispatcherServlet对象,并进行相应的配置,最后将其放到spring容器中交给容器进行管理。这就是spring的DispatcherServlet的自动装配原理。

DispatcherServlet请求映射

我们可以发现DispatcherServlet是一个Servlet,并且继承自HttpServlet,当我们自己实现HttpServlet类时,通常需要自己实现doGet和doPost方法。

image-20210502200414336

通过源码可以发现,这里HttpServletBean并没有实现doGet和doPost方法,但是在FrameworkServlet中实现了这两个方法:

image-20210502201003633

最终它们调用了processRequest方法进行请求的处理:

image-20210502201059424

这个方法在进行了一系列的初始化操作以后,调用了doService方法,doService方法在FrameworkServlet类中是一个抽象方法,所以这个方法的具体实现是在DispatcherServlet中具体实现的。

image-20210502201308331

在该方法中,除了设置了一系列的属性以外,调用了doDispatch方法进行了请求的分派,这个方法就是请求映射的关键之处。

doDispatch方法

从源码中我们可以发现,doDispatch方法首先通过getHandler方法获取到了处理请求的handler,然后通过调用这个handler来处理前端传递的请求。

image-20210502204441544

调用handler处理前端传递的请求。

image-20210502204609700

那么首先来看看getHandler方法。

getHandler

可以看出这个方法通过存储在HandlerMapping中的handler选择匹配当前请求的handler

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
   
   
   if (this.handlerMappings != null) {
   
   
      for (HandlerMapping mapping : this.handlerMappings) {
   
   
         // org.springframework.web.servlet.handler.AbstractHandlerMapping#getHandler
         HandlerExecutionChain handler = mapping.getHandler(request);
         if (handler != null) {
   
   
            return handler;
         }
      }
   }
   return null;
}

此时总共handlerMappings中共包含六个handlerMapping:

image-20210502205102987

此时可以发现所有的请求都存储在RequestMappingHandlerMapping中:

image-20210502205220958

接着会调用AbstractHandlerMapping#getHandler方法获取HandlerExecutionChain,我们继续深入进去看看它们是如何进行匹配的,通过调试过程中的函数调用我们可以发现匹配发生在getHandlerInternal方法中:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值