IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> SpringBoot学习笔记【part10】请求映射原理 -> 正文阅读

[Java知识库]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。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-02-01 20:27:55  更:2022-02-01 20:29:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 9:30:46-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码