Spring的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-06-16 15:10  水三丫  阅读(199)  评论(0)    收藏  举报