SpringBoot的请求映射原理

我们在进行web开发中,每次发请求是如何找到哪个方法去处理这个请求的。所谓请求映射的原理就是来查找源码中是如何完成这个处理的。我们知道SpringBoot中每个请求都会来到DispatcherServlet,底层还是使用SpringMVC,所以我们来看DispatcherServlet类。

该类在org.springframework.web.servlet包下:

进入到该类中,按快捷键“Ctrl+H”查看该类的继承树:

是间接继承了HttpServlet,那么一定会重写doGet()和doPost()方法,而DispatcherServlet类中没有重写doGet()和doPost()方法,那么我们就查看FrameworkServlet类中是否重写了,发现果然重写了,源码如下:

    protected final void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.processRequest(request, response);
    }

    protected final void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.processRequest(request, response);
    }

在两个方法中都调用了processRequest()方法,我们又查看processRequest()方法的源码,该方法的核心就是调用了doService()方法来处理请求和响应:

所以我们继续查看doService()方法源码,是一个抽象方法,那么我们需要看它的子类是否实现了该方法。

    protected abstract void doService(HttpServletRequest var1, HttpServletResponse var2) throws Exception;

我们又回到DispatcherServlet类,发现果然实现了doService()方法,该方法内的核心是调用了doDispatch()方法来处理请求和响应。

调用过程总结如下:请求首先到HttpServlet的doGet()方法,然后这个方法被FrameworkServlet类重写了,在该方法内又调用了该类的processRequest()方法,然后又调用了DispatcherServlet实现的doService()方法,最终交由doDispatcher()方法进行处理。

我们能够在doDispatcher()方法内成功打上断点,我们需要先在控制器类准备一个请求的处理,然后在浏览器访问执行:

@RestController
public class HelloController {

    @RequestMapping(value = "/hello", method = RequestMethod.GET)
    public String hello() {
        return "Hello SpringBoot";
    }
}

在doDispatcher()方法的第一行打上断点:

debug模式启动项目,然后在浏览器访问/hello请求

让代码走到mappedHandler.getHandler()所在行,这个方法决定哪个handler(controller中的方法)处理当前请求。然后放行,查看handler是什么。

选中mappedHandler = this.getHandler(processedRequest);右键单击出现如图面板,点击Evaluate Expression...计算结果

发现最终要执行的就是HelloController类中的hello()方法

继续将断点打在该行,但是执行到这里强行进入getHandler()方法内,查看如何生成的

查看handlerMappings的内容有五个处理器映射器

这里有一个handlerMapping,这是一个处理器映射器,SpringMVC根据它中的映射规则知道了哪个请求应该由哪个处理器(就是我们自己写的控制器类)处理。默认的handlerMapping有5个(如图),其中第一个RequestMappingHandlerMapping中保存了@RequestMapping和handler的映射规则。当我们的应用一启动,SpringMVC自动扫描所有的Controller并解析注解,把注解信息保存在handlerMapping里面。 然后通过循环遍历着5个handlerMapping,看哪个可以处理当前请求。

如上图,发现我们自己在controller中写的路径都存到了Map里面。然后通过mapping.getHandler(request)把请求对应的handler找到(也就是controller中对应的方法)完成映射。

所有的请求映射都在HandlerMapping中,SpringBoot自动配置了欢迎页的WelcomePageHandlerMapping,访问"/"就能访问到index.html,也自动配置了默认的RequestMappingHandlerMapping,当我们请求进来后,挨个尝试所有的HandlerMapping看是否有请求信息,如果有就找到这个请求对应的handler(就是我们写的控制器),如果没有则继续找下一个HandlerMapping,但如果我们需要一些自定义的映射处理,我们也可以自己通过@Bean给容器中放HandlerMapping。

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值