sss继 《SpringBoot:参数处理原理 ---- 8.2》这篇文章,我们继续分析复杂参数的请求原理,其实和上篇文章的过程差不多,也就是变相的分析mv返回后,我们怎么处理。

  • 复杂参数
  • 例子:
  • 为什么Map,Model参数解析后存放位置是相同的?(是)
  • Model 和 View解析后的参数和转发地址是怎么封装到mav中,并返回的呢?
  • 处理完的数据(也就是mav中的数据)怎么办?
  • 图解流程:


复杂参数

sssMap、Model(map、model里面的数据会被放在request的请求域 request.setAttribute)、
sssErrors/BindingResult、RedirectAttributes( 重定向携带数据)、ServletResponse(response)、
sssSessionStatus、UriComponentsBuilder、ServletUriComponentsBuilder
Map<String,Object> map,  Model model, HttpServletRequest request 都是可以给request域中放数据,
request.getAttribute(); 取数据
例子:
@GetMapping("/params")
    public String testParam(Map<String,Object> map ,
                            Model model,
                            HttpServletRequest requst,
                            HttpServletResponse response){
        map.put("hello" , "world666");
        model.addAttribute("world","Hello666");
        requst.setAttribute("message" , "HelloWorld");

        Cookie cookie = new Cookie("c1" , "v1");
        cookie.setDomain("localhost");
        response.addCookie(cookie);
        return "forward:/success";
    }
    @ResponseBody
    @GetMapping("/success")
    public Map success(HttpServletRequest request){
        Object msg1 = request.getAttribute("msg");
        HashMap<String, Object> map = new HashMap<>();
        Object hello = request.getAttribute("hello");
        Object world = request.getAttribute("world");
        Object message = request.getAttribute("message");

        map.put("reqMethod_msg",msg1);
        map.put("annotation_msg",msg);
        map.put("hello",hello);
        map.put("world",world);
        map.put("message",message);
        return  map;
    }
}

sss结果:

{"world":"Hello666","hello":"world666","message":"HelloWorld"}

dasdads

springboot 一个对象赋值给另一个对象 哪种更合适 springboot传参数 复杂对象_后端


sdsss【结论】:responce转发Cookie也可以的,Map<String,Object> map, Model model, HttpServletRequest request 都是可以给 request域中放数据。

为什么Map,Model参数解析后存放位置是相同的?(是)

sdsss通过deBug调试我们发现:

springboot 一个对象赋值给另一个对象 哪种更合适 springboot传参数 复杂对象_后端_02


springboot 一个对象赋值给另一个对象 哪种更合适 springboot传参数 复杂对象_spring boot_03


springboot 一个对象赋值给另一个对象 哪种更合适 springboot传参数 复杂对象_spring boot_04

sss通过源码我们可以得知:Map、Model类型的参数解析,最终返回的是相同的地址。

sdsss通过解析完参数,就要执行方法体,但是我们发现解析完的参数存放的map,model相关的参数是放到了相同地址的mavContainer中,并且返回值是forward:/success。

springboot 一个对象赋值给另一个对象 哪种更合适 springboot传参数 复杂对象_后端_05

Model 和 View解析后的参数和转发地址是怎么封装到mav中,并返回的呢?

sdsss当执行完方法体后,需要处理返回值:

springboot 一个对象赋值给另一个对象 哪种更合适 springboot传参数 复杂对象_sed_06


springboot 一个对象赋值给另一个对象 哪种更合适 springboot传参数 复杂对象_数据_07


sdsss怎么处理返回值呢?我们通过上面两幅图会发现所有的数据都放在 ModelAndViewContainer;包含要去的页面地址View(返回值)。还包含Model(map)数据。

sdsss处理完后,我们就要获取ModelAndView,然后返回:

sdsdsdsdsssvar15 = this.getModelAndView(mavContainer, modelFactory, webRequest);

springboot 一个对象赋值给另一个对象 哪种更合适 springboot传参数 复杂对象_后端_08

sdsss①、这个方法首先要做的是看是否更新模型(就是做一些绑定之类的工作):

springboot 一个对象赋值给另一个对象 哪种更合适 springboot传参数 复杂对象_java_09


springboot 一个对象赋值给另一个对象 哪种更合适 springboot传参数 复杂对象_数据_10

sdsss②、绑定或者不绑定后,然后再重新封装成ModelAndView。然后判断其是否是重定向数据,如果是,就再做处理。

springboot 一个对象赋值给另一个对象 哪种更合适 springboot传参数 复杂对象_spring boot_11

sdsss③、最后返回ModelAndView,对应的doDispatcher() 的

sdsdsdssmv = ha.handle(processedRequest, response, mappedHandler.getHandler());这个方法就完事了。
处理完的数据(也就是mav中的数据)怎么办?

sdsss对应的方法首先是doDispatcher()中的:mappedHandler.applyPostHandle(processedRequest, response, mv);,这是拦截器的相关工作。

springboot 一个对象赋值给另一个对象 哪种更合适 springboot传参数 复杂对象_sed_12


sdsss执行完后,就跳到了最重要的方法:处理派发结果!!! 他一定会把model中的东西放到请求域中:

sddsdssssthis.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);

sdsss①、首先是处理一些错误:

springboot 一个对象赋值给另一个对象 哪种更合适 springboot传参数 复杂对象_spring boot_13

sdsss

springboot 一个对象赋值给另一个对象 哪种更合适 springboot传参数 复杂对象_数据_14


sdsss②、对render()方法进行分析:

springboot 一个对象赋值给另一个对象 哪种更合适 springboot传参数 复杂对象_spring boot_15


springboot 一个对象赋值给另一个对象 哪种更合适 springboot传参数 复杂对象_spring boot_16

springboot 一个对象赋值给另一个对象 哪种更合适 springboot传参数 复杂对象_后端_17

sdsss当拿到相应的视图的URL地址后,就开始进行真正的转发:

springboot 一个对象赋值给另一个对象 哪种更合适 springboot传参数 复杂对象_后端_18

view.render(mv.getModelInternal(), request, response);
	=====》其中的核心方法如下
        Map<String, Object> mergedModel = this.createMergedOutputModel(model, request, response);
       ====>点击进入:
       		 if (model != null) { mergedModel.putAll(model);} 
       		 =====》也就是说将model中的数据全都返回到mergedModel中,而mergedModel是linkedHashmap.💦

sdsss接下来准备将合并的model转发出去:

springboot 一个对象赋值给另一个对象 哪种更合适 springboot传参数 复杂对象_后端_19


springboot 一个对象赋值给另一个对象 哪种更合适 springboot传参数 复杂对象_sed_20

sdsss①、exposeModelAsRequestAttributes 的源码。我们可以发现通过遍历将model中的对象放如到了request中,然后转发即可。(顾名思义就是暴漏Model,作为请求域的属性:)

springboot 一个对象赋值给另一个对象 哪种更合适 springboot传参数 复杂对象_后端_21

sdsss②、然后创建dispatcherPath,然后进行转发,即rd.forward(request,response);

图解流程:

springboot 一个对象赋值给另一个对象 哪种更合适 springboot传参数 复杂对象_spring boot_22

sdsss【注意点】:

sd dssss1、 mvContainer容器是在获取所有的参数解析器和返回值解析器那里生成的。

sddssss 2、在获得参数注解那一步,如果参数没有注解,则只能获得参数类型。