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
sdsss【结论】:responce转发Cookie也可以的,Map<String,Object> map, Model model, HttpServletRequest request 都是可以给 request域中放数据。
为什么Map,Model参数解析后存放位置是相同的?(是)
sdsss通过deBug调试我们发现:
sss通过源码我们可以得知:Map、Model类型的参数解析,最终返回的是相同的地址。
sdsss通过解析完参数,就要执行方法体,但是我们发现解析完的参数存放的map,model相关的参数是放到了相同地址的mavContainer中,并且返回值是forward:/success。
Model 和 View解析后的参数和转发地址是怎么封装到mav中,并返回的呢?
sdsss当执行完方法体后,需要处理返回值:
sdsss怎么处理返回值呢?我们通过上面两幅图会发现所有的数据都放在 ModelAndViewContainer;包含要去的页面地址View(返回值)。还包含Model(map)数据。
sdsss处理完后,我们就要获取ModelAndView,然后返回:
sdsdsdsdsssvar15 = this.getModelAndView(mavContainer, modelFactory, webRequest);
sdsss①、这个方法首先要做的是看是否更新模型(就是做一些绑定之类的工作):
sdsss②、绑定或者不绑定后,然后再重新封装成ModelAndView。然后判断其是否是重定向数据,如果是,就再做处理。
sdsss③、最后返回ModelAndView,对应的doDispatcher() 的
sdsdsdssmv = ha.handle(processedRequest, response, mappedHandler.getHandler());这个方法就完事了。
处理完的数据(也就是mav中的数据)怎么办?
sdsss对应的方法首先是doDispatcher()中的:mappedHandler.applyPostHandle(processedRequest, response, mv);
,这是拦截器的相关工作。
sdsss执行完后,就跳到了最重要的方法:处理派发结果!!! 他一定会把model中的东西放到请求域中:
sddsdssssthis.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
sdsss①、首先是处理一些错误:
sdsss
sdsss②、对render()方法进行分析:
sdsss当拿到相应的视图的URL地址后,就开始进行真正的转发:
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转发出去:
sdsss①、exposeModelAsRequestAttributes 的源码。我们可以发现通过遍历将model中的对象放如到了request中,然后转发即可。(顾名思义就是暴漏Model,作为请求域的属性:)
sdsss②、然后创建dispatcherPath,然后进行转发,即rd.forward(request,response);
图解流程:
sdsss【注意点】:
sd dssss1、 mvContainer容器是在获取所有的参数解析器和返回值解析器那里生成的。
sddssss 2、在获得参数注解那一步,如果参数没有注解,则只能获得参数类型。