Spring的Model 和 Map的原理源码解析

网友投稿 337 2022-07-22


Model 和 Map

为什么在Model和Map中放值传入后会出现在request的上面。

9.1、源码解析

准备测试代码

@GetMapping("/goto")

public String go(HttpServletRequest request,

Map 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 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

RewmqzxkNhquestMappingHandlerAdapter类中

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 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 model,

HttpServletRequest request) throws Exception {

model.forEach((name, value) -> {

if (value != null) {

request.setAttribute(name, value);

}

else {

request.removeAttribute(name);

}

});

}


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:SpringBoot项目使用 axis 调用webservice接口的实践记录
下一篇:Java如何实现字符串每隔4位加空格
相关文章

 发表评论

暂时没有评论,来抢沙发吧~