22.Model、Map原理

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);
       
      }
       
      });
       
      }
       

posted @ 2022-08-08 10:49  随遇而安==  阅读(156)  评论(0编辑  收藏  举报