Model 和 Map

为什么在Model和Map中放值传入后会出现在request的上面。

9.1、源码解析

  1. 准备测试代码

    @GetMapping("/goto")
    public String go(HttpServletRequest request,
    Map<String,Object> map,
    Model model){ request.setAttribute("msg","传过来....");
    map.put("map","map hello word!!");
    model.addAttribute("model","model hello word!!"); return "forward:success";
    } @ResponseBody
    @GetMapping("/success")
    public Map success(@RequestAttribute(value = "msg",required = false) String msg,
    HttpServletRequest request){
    Map<String,Object> hashMap = new HashMap<>(); Object msg1 = request.getAttribute("msg");
    Object map = request.getAttribute("map");
    Object model = request.getAttribute("model"); hashMap.put("map1",map);
    hashMap.put("model",model);
    hashMap.put("msg1",msg1); return hashMap;
    }
  2. 第一步进入DispatchServlet 的 doDispatch中

    • 主要的三步

      DispatchServlet类中的
      doDispatch方法
      // Determine handler for the current request.
      mappedHandler = getHandler(processedRequest);//获取反射的方法处理器
      // Determine handler adapter for the current request.
      //获取参数处理器
      HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
      // Actually invoke the handler.
      //反射执行方法和解析Model和Map
      mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
  3. 在获取参数阶段,解Model和Map

    • 获取Map 的 处理器器 MapMethodProcessor

    • 处理Map这个参数

      MapMethodProcessor类中的
      @Override
      @Nullable
      public Object resolveArgument(MethodParameter parameter,
      @Nullable ModelAndViewContainer mavContainer,
      NativeWebRequest webRequest,
      @Nullable WebDataBinderFactory binderFactory) throws Exception {
      Assert.state(mavContainer != null, "ModelAndViewContainer is required for model exposure"); return mavContainer.getModel();
      } 然后进入ModelAndViewContainer类中的
      private final ModelMap defaultModel = new BindingAwareModelMap();
      public ModelMap getModel() {
      if (useDefaultModel()) {
      return this.defaultModel;//获取ModelMap
      }
      ......
    • 把这个ModelMap对象返回

    • 获取Model的 处理器器 ModelMethodProcessor

    • 处理Model这个参数

      ModelMethodProcessor类中的
      @Override
      @Nullable
      public Object resolveArgument(MethodParameter parameter,
      @Nullable ModelAndViewContainer mavContainer,
      NativeWebRequest webRequest,
      @Nullable WebDataBinderFactory binderFactory) throws Exception { Assert.state(mavContainer != null, "ModelAndViewContainer is required for model exposure");
      return mavContainer.getModel();
      } 然后进入ModelAndViewContainer类中的
      private final ModelMap defaultModel = new BindingAwareModelMap();
      public ModelMap getModel() {
      if (useDefaultModel()) {
      return this.defaultModel;//获取ModelMap 这个和那个Map获取的是同一个
      }
      ......
    • 把同一个ModelMap对象返回

  4. 反射调用方法

    由于是同一个对象所有 map 和 model中的值都样,所以往map和Model放值都一样

  5. 把model和map的数据放入request

    • 第一步
    ServletInvocableHandlerMethod类中
    invokeAndHandle方法
    //获取返回值的一个处理器
    try {
    this.returnValueHandlers.handleReturnValue(
    returnValue, getReturnValueType(returnValue),
    mavContainer, webRequest);
    }
    HandlerMethodReturnValueHandlerComposite类中的
    HandlerMethodReturnValueHandler方法 进行获取

    这里获取的ViewNameMethodReturnValueHandler这个处理器

    • 第二步

      把Map和 Model携带的参数和返回值(路径)进行整合为ModelAndView

    RequestMappingHandlerAdapter类中
    handleInternal方法
    ...
    ModelAndView mav;
    ...
    mav = invokeHandlerMethod(request, response, handlerMethod);
    ...

    • 第三步

      准备派发和放入参数

      DispatchServlet类中的
      doDispatch方法
      render(mv, request, response);
      view.render(mv.getModelInternal(), request, response); AbstractView类中的
      render方法
      //把BindingAwareModelMap的参数封装为Map
      Map<String, Object> mergedModel = createMergedOutputModel(model,
      request, response);
      prepareResponse(request, response);
      //准备方法和放入参数到reques中
      renderMergedOutputModel(mergedModel, getRequestToExpose(request),
      response);
      InternalResourceView类中的
      renderMergedOutputModel
      // Expose the model object as request attributes.
      exposeModelAsRequestAttributes(model, request);//把参数放入到request中
      AbstractView类中的
      //把参数放入到原生的request域中
      protected void exposeModelAsRequestAttributes(Map<String, Object> model,
      HttpServletRequest request) throws Exception {
      model.forEach((name, value) -> {
      if (value != null) {
      request.setAttribute(name, value);
      }
      else {
      request.removeAttribute(name);
      }
      });
      }

Spring的Model 和 Map的原理的更多相关文章

  1. Spring框架系列(14) - SpringMVC实现原理之DispatcherServlet处理请求的过程

    前文我们有了IOC的源码基础以及SpringMVC的基础,我们便可以进一步深入理解SpringMVC主要实现原理,包含DispatcherServlet的初始化过程和DispatcherServlet ...

  2. 理解Spring MVC Model Attribute和Session Attribute

    作为一名 Java Web 应用开发者,你已经快速学习了 request(HttpServletRequest)和 session(HttpSession)作用域.在设计和构建 Java Web 应用 ...

  3. SpringMVC(二)--处理数据模型、ModelAndView、Model、Map、重定向、@ModelAttribute、

    1.处理模型数据 Spring MVC 提供了以下几种途径输出模型数据:      – ModelAndView:处理方法返回值类型为 ModelAndView 时, 方法体即可通过该对象添加模型数据 ...

  4. Spring中Model、ModelMap及ModelAndView之间的区别

    Spring中Model.ModelMap及ModelAndView之间的区别   1. Model(org.springframework.ui.Model)Model是一个接口,包含addAttr ...

  5. HashMap,Hashtable,ConcurrentHashMap 和 synchronized Map 的原理和区别

    HashMap 是否是线程安全的,如何在线程安全的前提下使用 HashMap,其实也就是HashMap,Hashtable,ConcurrentHashMap 和 synchronized Map 的 ...

  6. 【译】理解Spring MVC Model Attribute 和 Session Attribute

    作为一名 Java Web 应用开发者,你已经快速学习了 request(HttpServletRequest)和 session(HttpSession)作用域.在设计和构建 Java Web 应用 ...

  7. ModelAndView存取数Model、Map、ModelMap

    1.从名字上看ModelAndView中的Model代表模型,View代表视图,这个名字就很好地解释了该类的作用.(对应mvc配置,寻找模型,返回视图.) 2.业务处理器调用模型层处理完用户请求后,把 ...

  8. Spring Boot 实现配置文件加解密原理

    Spring Boot 配置文件加解密原理就这么简单 背景 接上文<失踪人口回归,mybatis-plus 3.3.2 发布>[1] ,提供了一个非常实用的功能 「数据安全保护」 功能,不 ...

  9. Spring框架系列(13) - SpringMVC实现原理之DispatcherServlet的初始化过程

    前文我们有了IOC的源码基础以及SpringMVC的基础,我们便可以进一步深入理解SpringMVC主要实现原理,包含DispatcherServlet的初始化过程和DispatcherServlet ...

随机推荐

  1. CentOS7软件环境

    一.软件环境 1.1 centos7 [root@centos7 ~]# cat /etc/redhat-release CentOS Linux release 7.4.1708 (Core) [r ...

  2. 做一个能对标阿里云的前端APM工具(下)

    上篇请访问这里做一个能对标阿里云的前端APM工具(上) 样本多样性问题 上一小节中的实施方案是微观的,即单次性的.具体的.但是从宏观上看,我需要保证性能测试是公允的,符合大众预期的.为了达到这种效果, ...

  3. 基于.NetCore开发博客项目 StarBlog - (11) 实现访问统计

    系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...

  4. 支付宝开放平台--网页&移动应用(一)

    前提是先在支付宝上签约自己需要的支付宝功能,然后支付宝开放平台才能设置你需要的功能 一:支付宝开放平台登录 登录进入支付宝开放平台 二:根据自己的需求创建应用(我是用的网页&移动应用) 三:点 ...

  5. Python装饰器Decorators

    def hi(name="yasoob"): return "hi " + name print(hi()) # 我们甚至可以将一个函数赋值给一个变量,比如 g ...

  6. 回流&重绘

    浏览器加载解析页面:把HTML解析为DOM树,解析CSS生成CSSOM树,HTML DOM树和CSSOM树组合构建render树,首次触发回流和重绘后将页面结构信息发送给GPU进行绘制渲染. 回流:当 ...

  7. Docker容器编译安装Redis

    Docker容器编译安装Redis 1.创建容器 -i 交互模式 -d 后端运行 -h 容器的hostname --name 容器名 --network 网卡 --ip IP地址 -p 端口映射 -- ...

  8. ESXI系列问题整理以及记录——使用Windows PowerShell中的SSH功能连接ESXI控制台

    首先进入ESXI管理页面,开启ESXI的SSH功能 接下来到位于同一局域网的Win主机上开启Powershell,如果ESXI主机的IP地址为192.168.1.77,则在Powershell中输入: ...

  9. SAP BOM 读取

    1.查找 物料号.工厂.物料描述. 表:MARA MARC MAKT 逻辑: 输入物料(选择选项)中的物料编号(MARA-MATNR)和                       输入工厂(选择选项 ...

  10. 02 CSS块级元素和行内元素

    02 CSS块级元素和行内元素 划分依据:根据标签内部可以存放的元素内容不同进行划分,它与CSS样式无关. 要先了解这个 得先了解 什么是容器级别的标签和文本级? 容器级标签 什么是容器级标签? 内部 ...