栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringBoot学习笔记【part10】请求映射原理

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringBoot学习笔记【part10】请求映射原理

SpringBoot 学习笔记 Part10 1. 请求映射

从@RequestMapping标注处理什么请求,到控制器方法的方法体返回值,这个过程就叫做请求映射,如下:

    @RequestMapping("hello")
    public String hello(){
        return "Hello SpringBoot 2 !";
    }

2. 请求映射原理 2.1 DispatcherServlet

springboot 所有的请求过来都会经过 DispatcherServlet,因为springboot底层仍用的是 springmvc,所以 DispatcherServlet 是处理所有请求的开始。

前往底层,我们可以发现 DispatcherServlet 最终继承于原生Servlet—— HttpServlet,其中继承树为 DispatcherServlet -> frameworkServlet -> HttpServletBean -> HttpServlet。

现在我们想知道在哪个派生类中重写了 doGet 和 doPost,前往底层源码可以发现,在 frameworkServlet 中有如下代码:

public abstract class frameworkServlet extends HttpServletBean implements ApplicationContextAware {
    
    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);
    }

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

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

在 frameworkServlet 的处理请求方法中都调用了本类的 processRequest( ) 方法,这个方法经分析,有大量初始化和清理操作,其中最重要的是它调用的 doService( ) 方法。

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

追踪该 doService( ) 方法,我们发现这也是一个本类的方法,是一个抽象方法。不难推测,这个抽象方法将在下一个派生类也就是 DispatcherServlet 中实现。

protected abstract void doService(HttpServletRequest request, HttpServletResponse response) throws Exception;

在 DispatcherServlet 的 doService 的实现方法中,有大量的处理,但我们最终把目光聚集到 doDispatcher 方法上。

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
    
    this.doDispatch(request, response);
    
}

我们最终发现, doDispatcher 方法才是真正有功能的方法,它检查文件上传、确定当前请求的处理程序(找到当前请求使用哪个Controller方法处理) 等。

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
	
    processedRequest = this.checkMultipart(request);
    mappedHandler = this.getHandler(processedRequest);
    
}

总结:当有请求进来时,调用顺序为:HttpServlet.doGet() -> frameworkServlet.processRequest().doService() -> DispatcherServlet.doService().doDispatch()


2.2 doDispatch方法

doDispatcher 方法才是真正有请求处理功能的方法,它检查文件上传、确定当前请求的处理程序(找到当前请求使用哪个Controller方法处理) 等。节选源码如下,逐步分析。

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
	
    processedRequest = this.checkMultipart(request); //检查是不是文件上传
    multipartRequestParsed = processedRequest != request;
    mappedHandler = this.getHandler(processedRequest); //找到当前请求使用哪个Controller方法处理
	
}

2.3 getHandler方法

从 doDispatch方法 进入 getHandler方法。

@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    if (this.handlerMappings != null)
    
}

HandlerMappings 译为处理器映射,即 /xxx 将被映射为 xxx,所有的处理器映射都被存在 handlerMappings 对象里。对第一行handlerMappings判空代码进行debug调试,可以发现存在5个handlerMapping。

其中下标为1的就是我们之前学习过的欢迎页,即springmvc在该对象里储存了欢迎页的映射规则。不难发现,下标为0的 RequestMappingHandlerMapping的前半段RequestMapping酷似我们之前学习过的注解 @RequestMapping,经过验证,这里就保存着我们所有被 @RequestMapping 标注过的 Controller 方法和handler的映射规则。其实项目一启动,@RequestMapping的映射规则就被springmvc解析并存储了。

继续 getHandler 方法的分析,下面是一个循环,遍历所有 @RequestMapping 映射规则意在找到对应的handler方法。通过debug,可以找到mappingRegistry对象,我之前编写的rest请求映射,都存在这里面。

总结:所有的请求映射都存在HandlerMappings中。


2.4 HandlerMappings

SpringBoot 中所有的请求映射都在 HandlerMappings 里。

在handlerMappings容器中我们可以发现,SpringBoot 自动配置了默认的 RequestMappingHandlerMapping、自动配置了欢迎页的 WelcomePageHandlerMapping(即使用 / 能访问到 index.html),以及之后学习的 BeanNameHandlerMapping、RouterFunctionMapping以及 SimpleUrlHandlerMapping。

SpringBoot的请求进来,会在getHandler方法里挨个尝试所有的 HandlerMapping 看其是否有对应的请求信息。若有则找到这个请求对应的 handler 并调用,若没有则去找下一个 HandlerMapping。


自定义HandlerMapping:
若在一些场景(如不同版本的方法调用:/api/v1/user、/api/v2/user)我们需要自定义一些映射处理,我们也可以自己给容器中放 自定义HandlerMapping。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/719190.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号