Spring的Model 和 Map的原理源码解析
作者:水三丫
这篇文章主要介绍了Spring的Model 和 Map的原理解析,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
Model 和 Map
为什么在Model和Map中放值传入后会出现在request的上面。
9.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; }
第一步进入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());
在获取参数阶段,解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对象返回
反射调用方法
由于是同一个对象所有 map 和 model中的值都样,所以往map和Model放值都一样
把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的原理源码解析的文章就介绍到这了,更多相关Spring Model 和 Map内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!