在DispatcherServlet.java的doDispatch方法中,springmvc通过handlermapping里面找哪个handler能处理请求,handler封装了目标方法的信息,

mappedHandler = getHandler(processedRequest);

然后为当前的handler找到一个适配器HandlerAdapter,寻找的过程为:在DispatcherServlet.java的getHandlerAdapter方法中,挨个匹配,判断当前adapter是否支持当前handler,判断方法为只要handler是handlerMethod类型就生效,就支持

HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
if (this.handlerAdapters != null) {
for (HandlerAdapter adapter : this.handlerAdapters) {
if (adapter.supports(handler)) {
return adapter;
}
}
}

找到适配器以后判断当前请求是不是“GET”方法以及“HEAD”,“HEAD”不是服务器真正处理的

适配器HandlerAdapter把(目标方法、request、response)传入handle执行目标方法

mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

怎么执行目标方法:

  • 先得到handler
return this.handler;
  • 再进入内部处理细节RequestMappingHandlerAdapter.java,调用的invokeHandlerMethod就是执行目标方法
mav = invokeHandlerMethod(request,response,handlerMethod);
  • 在RequestMappingHandlerAdapter.java的invokeHandlerMethod方法中,

    • 为invocableMethod方法设置参数解析器argumentResolvers,参数解析器确定将要执行的目标方法的每一个参数的值是什么

      • 当前解析器是否支持解析这种参数

      • 支持就调用 resolveArgument

    • 为invocableMethod方法设置返回值处理器returnValueHandlers

  • 把26个argumentResolvers和15个returnValueHandlers都放入目标方法包装的ServletInvocableHandlerMethod中

  • 然后真正执行目标方法的语句

    invocableMethod.invokeAndHandle(WebRequest,mavContainer);
    • 在ServletInvocableHandlerMethod.java的invokeAndHandle方法中,执行了controller

      Object returnValue = invokeForRequest(webRequest,mavContainer,proviedArgs);
      • step into 进入InvocableHandlerMethod.java,确定目标方法每一个参数的值

        Object[] agrs = getMethodArgumentValues(request,mavContainer,providerArgs)
        • 在InvocableHandlerMethod.java的getMethodArgumentValues方法中,先获取方法所有的参数声明(详细信息)。

          MethodParameter[] parameters = getMethodParameters();
        • 判断参数是否为空,为空则无需确定任何值直接返回;

          if (ObjectUtils.isEmpty(parameters)) {
          return EMPTY_ARGS;
          }

          如果有参数列表,new一个Object[],参数列表有多少个Object[]就有多长

          Object[] args = new Object[parameters.length];
          for (int i = 0; i < parameters.length; i++) {
          MethodParameter parameter = parameters[i];
          parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
          args[i] = findProvidedArgument(parameter, providedArgs);

          先声明args遍历parameters,给args[i]赋值,args[i]的值解析器解析了才有

        • 解析之前,判断26个解析器是不是supportsParamter支持这个参数类型。

          this.resolvers.supportsParameter(parameter)
          • HandlerMethodArgumentResolverComposite.java的getArgumentResolver方法中

          • 获取一个缓存result

          • result==null,进入增强for循环,逐个确定26个解析器谁能支持这种参数

            • supportsParameter方法,传来的参数有没有hasParameterAnnotation标注注解
            • 没有就return false
            • 如果标了,再判断参数是否map类型,
            • return true支持解析
          • 当前resolver支持解析,放到缓存里边,判断成功,进入解析

        • 解析参数

          this.resolvers.resolveArgument
          • HandlerMethodArgumentResolverComposite.java的resolverArgument方法中,先拿到所有的参数解析器getArgumentResolver
          • 调用参数解析器的resolverArgument方法进行解析
            • 获取参数名字信息
            • 解析参数的名字,placeholderResolved、BeanExpressionResolver解析evaluate计算名字,按照正则匹配的方式
            • 解析参数的值
              • uriTemlateVars 在request请求域中拿到值;UrlPathHelper会把uri地址里边的所有的路径变量全部解析出来并保存到请求域中
        • 遍历循环所有参数

      • 最终返回args,args就是确定好的值

    • 处理返回结果的时候,把mavContainer传进去,

      this.returnValueHandlers.handlerReturnValue
      • 在handlerMethod.java的getReturnValueType方法中获取返回的结果类型

      • HandlerMethodArgumentResolverComposite.java的handleReturnValue方法中,

        找到返回值的处理器

        如果返回值是一个字符串,拿到字符串然后保存到mavContainer

    • 返回值处理完以后,getModelAndView

  • 目标方法执行完成

    将所有的数据都放在 ModelAndViewContainer;包含要去的页面地址View。还包含Model数据。

  • 从ModelAndViewContainer拿到默认的Model,updateBindingResult,拿到key放到绑定里边,又被封装成ModelAndView,然后返回这个新封装的mav

    • 处理派发结果

      processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);

      拿到所有请求域中的属性,解析得到视图名

      渲染页面

      view.render(mv.getModelInternal(),request,response);

      拿到页面数据

      createMergeOutputModel(model,request,response);
      创造合并的输出模型

      如果model不等于空

      mergeModel.putAll(model)//即把数据转移到HashMap

      渲染合并输出的模型数据

      renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
      • 把上面的Hashmap传进来了

      • 拿到请求对象,获取的原生的Servletrequest

        return originalRequest
      • 暴露模型作为请求域属性

        // Expose the model object as request attributes.
        exposeModelAsRequestAttributes(model, request);
        • 把model里面的东西进行遍历
        • 遍历以后每一个request setAttribute

SpringMVC底层——请求参数处理流程描述的更多相关文章

  1. 16 SpringMVC 的请求参数的绑定与常用注解

    1.SpringMVC 绑定请求参数 (1)支持的数据类型 基本类型参数: 包括基本类型和 String 类型POJO 类型参数: 包括实体类,以及关联的实体类数组和集合类型参数: 包括 List 结 ...

  2. SpringMVC之请求参数的获取方式

    转载出处:https://www.toutiao.com/i6510822190219264516/ SpringMVC之请求参数的获取方式 常见的一个web服务,如何获取请求参数? 一般最常见的请求 ...

  3. SpringMVC处理请求和返回流程

    流程描述:一个url请求,找打指定的requestMapping再返回指定的jsp界面 通过url拿到指定的java方法 HandlerExecutionChain  mappedHandler = ...

  4. SpringMVC接受请求参数、

    1. 接收请求参数 1.1. [不推荐]通过HttpServletRequest 在处理请求的方法中,添加HttpServletRequest对象作为参数,在方法体中,直接调用参数对象的getPara ...

  5. SpringMVC RequestMapping & 请求参数

    SpringMVC 概述 Spring 为展现层提供的基于 MVC 设计理念的优秀的Web 框架,是目前最主流的 MVC 框架之一 Spring3.0 后全面超越 Struts2,成为最优秀的 MVC ...

  6. SpringMVC 接受请求参数、作用域传值

    目录 原生servlet接收参数 Spring MVC最基础的参数获取 接收基本数据类型参数 方法参数列表和请求参数不一致的处理方式 接收对象引用数据类型 接收复选框这种多个同名的参数 接收obj.f ...

  7. SpringMVC 获取请求参数

    1.获取Request response对象 在SpringMVC的注解开发中,可以选择性的接收Request和Response对象来使用 2.获取request对象请求参数 a.通过request对 ...

  8. SpringMVC——映射请求参数

    Spring MVC 通过分析处理方法的签名,将 HTTP 请求信息绑定到处理方法的相应人参中. @PathVariable @RequestParam @RequestHeader 等) Sprin ...

  9. SpringMVC获取请求参数-POJO类型参数

    1.Controller中的业务方法的POJO参数的属性名与请求参数一致,参数值会自动映射匹配 1.创建POJO类 public class User { private String usernam ...

随机推荐

  1. 记一次burp suite文件上传漏洞实验

    一·文件上传漏洞概念 文件上传漏洞是指 Web 服务器允许用户在没有充分验证文件名称.类型.内容或大小等内容的情况下将文件上传到其文件系统.未能正确执行这些限制可能意味着 即使是基本的图像上传功能也可 ...

  2. ChCore Lab1 机器启动 实验笔记

    本文为上海交大 ipads 研究所陈海波老师等人所著的<现代操作系统:原理与实现>的课程实验(LAB)的学习笔记的第一篇. 书籍官网:现代操作系统:原理与实现,里面有实验的参考指南和代码仓 ...

  3. 如何使用Docker构建前端项目

    原文链接 Docker单独部署前端项目和Node项目是非常便捷的,在这里分享一下Docker的使用,主要聊聊它的部署实践.(我是window10专业版安装Docker) Docker Docker是一 ...

  4. AC自动机:Tire树+KMP

    简介 AC自动机是一个多模式匹配算法,在模式匹配领域被广泛应用,举一个经典的例子,违禁词查找并替换为***.AC自动机其实是Trie树和KMP 算法的结合,首先将多模式串建立一个Tire树,然后结合K ...

  5. 111_Power Pivot 24小时维度:累计、同比、环比相关

    博客:www.jiaopengzi.com 焦棚子的文章目录 请点击下载附件 一.背景 今天有朋友讨论怎么做每天24小时维度的工作量计算(运营类企业,每天24小时都在运营)需求如下: 1.从0时到23 ...

  6. 从标准输入流中读取并执行shell指定函数

    巧妙的ohmytmux配置 看oh my tmux的配置,发现他们很巧妙的将配置和shell函数放到一个文件里 比如切换鼠标模式的相关配置和shell函数, # : << EOF # .. ...

  7. Fail2ban 配置详解 配置说明

    fail2ban的配置主要由基础配置(fail2ban.conf)和监禁配置(jail.conf)两部分组成. fail2ban的配置采用标签块"[块名]"和键值"key ...

  8. 一些实验中用过的python函数/方法(持续更新)

    衡量运行时间 很多时候你需要计算某段代码执行所需的时间,可以使用 time 模块来实现这个功能. import time startTime = time.time() # write your co ...

  9. Java变量, 常量和作用域

    目录 变量 作用域 局部变量 实例变量 类变量 常量 命名规范 视频课程 变量 变量就是可以变化的量 Java是一种强类型的语言, 每个变量都必须声明其类型 Java变量是程序中最基本的存储单元, 其 ...

  10. AR Engine运动跟踪能力,高精度实现沉浸式AR体验

    随着电子产品的普遍应用,AR技术也开始广泛普及,在游戏.电商.家装等领域都有涉及.比如,在室内设计时,我们可以通过AR技术在实际场景中进行虚拟软装的搭配,运用华为AR Engine运动跟踪能力在实际应 ...