【Spring MVC研究】DispatcherServlet如何处理请求(doDispatcher方法)

文章目录

  • [1. 最经典的MVC的使用情况](#1. 最经典的MVC的使用情况)
  • [2. 经典情况相关的组件](#2. 经典情况相关的组件)
  • [3. 执行](#3. 执行)
    • [3.1. 先看DispatcherServlet的总体过程](#3.1. 先看DispatcherServlet的总体过程)
    • [3.2. 再看`RequestMappingHandlerAdapter`的总体过程](#3.2. 再看RequestMappingHandlerAdapter的总体过程)
      • [3.2.1. RequestParamMethodArgumentResolver](#3.2.1. RequestParamMethodArgumentResolver)
      • [3.2.2. 反射调用 Controller 的方法](#3.2.2. 反射调用 Controller 的方法)
      • [3.2.3. RequestResponseBodyMethodProcessor](#3.2.3. RequestResponseBodyMethodProcessor)
  • [4. 总结](#4. 总结)

本文以"最经典"的情况分析了 DispatcherServlet 处理请求的全部过程。通读全文,读者应该对总体框架有一定的认识,且要求今后能有能力把 mvc 的其他组件原理"嵌入到总体框架中"。

1. 最经典的MVC的使用情况

这个过程很长,设计的到 web 组件很多,所以需要以一个最常见的情况作为"经典情况"来简化分析过程。突破之后再在对总体流程和框架的基础上,往上面新的补充内容。为了方便我讲解,我以:
"经典情况"是:Controller 中的@RequestMapping,方法的参数贴了@RequestParam注解,返回值上贴了@ResponseBody注解

搞完"经典情况",后续的其他 mvc 组件作者会一个一个的分析。

2. 经典情况相关的组件

RequestMappingHandlerMapping(请求映射器)

功能:把请求 request 映射到 handler;根据路径匹配

对应关系:只要我们的 Controller 写的路径匹配上了请求就可以了,假设匹配上。

HandlerMethod(处理请求)

功能:具体处理请求的

对应关系:对应是 Controller 中的方法

HandlerExecutionChain(处理器链)

功能:等于"处理器" + "匹配的拦截器"

对应关系:这里就是等于:"HandlerMethod + 匹配到的拦截器MappedInterceptor"

RequestMappingHandlerAdapter(对HandlerExecutionChain 再次包装)

记住:反正就是由RequestMappingHandlerAdapter 开始执行的就可以了。

RequestParamMethodArgumentResolver (参数解析器)

功能:专门处理 @RequestParam 注解的

对应关系:从请求 request 中解析出参数(调用 ServletRequest的 getParameterValues方法)

RequestResponseBodyMethodProcessor(返回值处理器)

功能:专门刚好处理 @ResponseBody注解。

3. 执行

3.1. 先看DispatcherServlet的总体过程

DispatcherServlet 的doDispatch方法的总体执行过程:

  • getHandler(1)
  • getHandlerAdapter(2)
  • applyPreHandle(3)
  • handle(重点:真正处理)(4)
  • applyPostHandle(5)

在(1)处得到 HandlerExecutionChain,包含 HandlerMethod和 MappedInterceptor

在(2)处得到 RequestMappingHandlerAdapter

在(3)处,执行MappedInterceptor的 preHandle方法

在(4)处,执行 RequestMappingHandlerAdapter的 handler方法

在(5)处,执行MappedInterceptor的 postHandle方法

3.2. 再看RequestMappingHandlerAdapter的总体过程

继续看 RequestMappingHandlerAdapter的 handler方法的总体过程:

注意:执行顺序是从左到右从上到下执行的

  • 封装为ServletInvocableHandlerMethod(1)
  • invokeAndHandle
    • invokeForRequest
      • getMethodArgumentValues(解析参数)
        • resolveArgument解析参数
          • getArgumentResolver(得到"参数解析器")
          • resolveArgument(真正解析)
      • doInvoke(具体执行)
    • handleReturnValue(处理返回值)
      • selectHandler
      • handleReturnValue
  • getModelAndView(2)

主要就只有 3 个关键过程(上面已加粗说明):

1、按 Controller 方法的要求解析参数。用的是 RequestParamMethodArgumentResolver

2、执行 Controller 方法。

3、处理 Controller 方法的返回值。用的是 RequestResponseBodyMethodProcessor

下面简单提一下其他过程(按序号):

在(1)处,把真正的执行的组件HandlerMethod 一顿疯狂包装成ServletInvocableHandlerMethod

比如就包装了 web 数据绑定器:WebDataBinder

在(2)处,处理视图,现在都是前后端开发,不用视图技术了。作者不讲,略,自己搞。

3.2.1. RequestParamMethodArgumentResolver

  • 支持的参数

在它的 supportsParameter 方法中,表明了支持"参数上贴了@RequestParam注解的参数"

  • 执行解析参数

1、 调用RequestParamMethodArgumentResolver的resolveArgument方法,

2、 会调用到RequestParamMethodArgumentResolver 的resolveName方法

3、会调用到解析文件的multipartRequest方法 和 从请求获取参数的 request.getParameterValues方法

4、解析之后还没有结束,还需要转换成 Controller 方法需要的参数类型(略,这就是另外的小细节故事了)

截止目前:也就通过从请求中获取参数完成了 Controller 方法参数的解析,

3.2.2. 反射调用 Controller 的方法

没什么好讲的,反射调用 Controller 的方法。

3.2.3. RequestResponseBodyMethodProcessor

  • 支持的类型

在supportsReturnType方法中表明了支持的类型是方法上@ResponseBody注解

  • 处理返回值

1、会调用到RequestResponseBodyMethodProcessor 的 handleReturnValue方法

2、会调用writeWithMessageConverters方法

3、最后直接调用"消息转换器"messageConverters把"返回值写到流里面去了"

注意:既然既然写到响应流 response 里面去了,响应就结束了,后面的视图处理过程就没了。

4. 总结

读完全文,读者要求掌握以下组件的工作情况。(对细节不需要苛责,但是一定要能知道 ** 组件的功能 **和 **组件在流程中的位置**。

  • RequestMappingHandlerMapping(请求映射器)
  • HandlerMethod(处理请求)
  • HandlerExecutionChain(处理器链)
  • RequestMappingHandlerAdapter(对HandlerExecutionChain 再次包装)
  • RequestParamMethodArgumentResolver(参数解析器)
  • RequestResponseBodyMethodProcessor(返回值处理器)
相关推荐
2301_780789662 小时前
跨平台适配!SDK 游戏盾兼容全终端游戏场景
java·网络·ddos
学长毕设3 小时前
基于springboot的食品仓库管理系统
java·spring boot·后端
步行cgn3 小时前
FormHttpMessageConverter 详解:Spring MVC 中表单数据的读写转换器
java·spring·mvc
龙亘川3 小时前
构建城市公共安全数字底座:亘川智城智慧安防系统全维度解读
java·大数据·开发语言·人工智能·信息可视化
金銀銅鐵3 小时前
[Java] 用 CLI 展示 EnumMap 增删键值对时的内部变化
java·源码·ai编程
秋天的怀念_David4 小时前
第二十二夜 · 数字迷雾
java·程序人生·算法
Raas1004 小时前
AI网关部署方案?从部署到上线全流程
java·开发语言·人工智能·gateway·ai网关·企业级ai网关·企业级ai产品
niucloud-admin5 小时前
NIUCLOUD PHP SAAS上门家政使用文档:城市管理
java·前端·php
霸道流氓气质5 小时前
智能客服组件:分层意图识别、RAG Advisor 与人工转接状态机的 Vue3 + Spring AI 生产级实战
java·人工智能·spring
captain3766 小时前
MyBatis操作数据库(入门2)
java·数据库·spring boot·后端·spring·mybatis