Spring的Model?和?Map的原理源碼解析
Model 和 Map
為什么在Model和Map中放值傳入后會(huì)出現(xiàn)在request的上面。
9.1、源碼解析
準(zhǔn)備測(cè)試代碼
@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;
}第一步進(jìn)入DispatchServlet 的 doDispatch中
主要的三步
DispatchServlet類中的
doDispatch方法
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);//獲取反射的方法處理器
// Determine handler adapter for the current request.
//獲取參數(shù)處理器
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Actually invoke the handler.
//反射執(zhí)行方法和解析Model和Map
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());在獲取參數(shù)階段,解Model和Map
- 獲取Map 的 處理器器 MapMethodProcessor
- 處理Map這個(gè)參數(shù)
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();
}
然后進(jìn)入ModelAndViewContainer類中的
private final ModelMap defaultModel = new BindingAwareModelMap();
public ModelMap getModel() {
if (useDefaultModel()) {
return this.defaultModel;//獲取ModelMap
}
......- 把這個(gè)ModelMap對(duì)象返回
- 獲取Model的 處理器器 ModelMethodProcessor
- 處理Model這個(gè)參數(shù)
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();
}
然后進(jìn)入ModelAndViewContainer類中的
private final ModelMap defaultModel = new BindingAwareModelMap();
public ModelMap getModel() {
if (useDefaultModel()) {
return this.defaultModel;//獲取ModelMap 這個(gè)和那個(gè)Map獲取的是同一個(gè)
}
......把同一個(gè)ModelMap對(duì)象返回

反射調(diào)用方法
由于是同一個(gè)對(duì)象所有 map 和 model中的值都樣,所以往map和Model放值都一樣



把model和map的數(shù)據(jù)放入request
第一步
ServletInvocableHandlerMethod類中
invokeAndHandle方法
//獲取返回值的一個(gè)處理器
try {
this.returnValueHandlers.handleReturnValue(
returnValue, getReturnValueType(returnValue),
mavContainer, webRequest);
}
HandlerMethodReturnValueHandlerComposite類中的
HandlerMethodReturnValueHandler方法 進(jìn)行獲取這里獲取的ViewNameMethodReturnValueHandler這個(gè)處理器

第二步
把Map和 Model攜帶的參數(shù)和返回值(路徑)進(jìn)行整合為ModelAndView
RequestMappingHandlerAdapter類中
handleInternal方法
...
ModelAndView mav;
...
mav = invokeHandlerMethod(request, response, handlerMethod);
...第三步
準(zhǔn)備派發(fā)和放入?yún)?shù)
DispatchServlet類中的
doDispatch方法
render(mv, request, response);
view.render(mv.getModelInternal(), request, response);
AbstractView類中的
render方法
//把BindingAwareModelMap的參數(shù)封裝為Map
Map<String, Object> mergedModel = createMergedOutputModel(model,
request, response);
prepareResponse(request, response);
//準(zhǔn)備方法和放入?yún)?shù)到reques中
renderMergedOutputModel(mergedModel, getRequestToExpose(request),
response);
InternalResourceView類中的
renderMergedOutputModel
// Expose the model object as request attributes.
exposeModelAsRequestAttributes(model, request);//把參數(shù)放入到request中
AbstractView類中的
//把參數(shù)放入到原生的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);
}
});
}
到此這篇關(guān)于Spring的Model 和 Map的原理源碼解析的文章就介紹到這了,更多相關(guān)Spring Model 和 Map內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Springboot整合Dozer實(shí)現(xiàn)深度復(fù)制的方法
Dozer是一種Java?Bean到Java?Bean的映射器,遞歸地將數(shù)據(jù)從一個(gè)對(duì)象復(fù)制到另一個(gè)對(duì)象,它是一個(gè)強(qiáng)大的,通用的,靈活的,可重用的和可配置的開源映射框架,本文給大家介紹Springboot整合Dozer的相關(guān)知識(shí),感興趣的朋友跟隨小編一起看看吧2022-03-03
Java內(nèi)存模型之重排序的相關(guān)知識(shí)總結(jié)
重排序是指編譯器和處理器為了優(yōu)化性能而對(duì)指令序列進(jìn)行重新排序的一種手段,文中詳細(xì)介紹了Java重排序的相關(guān)知識(shí),需要的朋友可以參考下2021-06-06
springBoot如何動(dòng)態(tài)加載資源文件
這篇文章主要介紹了springBoot如何動(dòng)態(tài)加載資源文件,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
Kotlin基礎(chǔ)教程之Run,標(biāo)簽Label,函數(shù)Function-Type
這篇文章主要介紹了Kotlin基礎(chǔ)教程之Run,標(biāo)簽Label,函數(shù)Function-Type的相關(guān)資料,需要的朋友可以參考下2017-05-05
Java國際化簡(jiǎn)介_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要為大家簡(jiǎn)單介紹了Java國際化的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07
java實(shí)現(xiàn)百度坐標(biāo)的摩卡托坐標(biāo)與火星坐標(biāo)轉(zhuǎn)換的示例
這篇文章主要介紹了java實(shí)現(xiàn)百度坐標(biāo)的摩卡托坐標(biāo)與火星坐標(biāo)轉(zhuǎn)換的示例,需要的朋友可以參考下2014-03-03
Eclipse下基于Java的OpenCV開發(fā)環(huán)境配置教程
這篇文章主要為大家詳細(xì)介紹了Eclipse下基于Java的OpenCV開發(fā)環(huán)境配置教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07
Java并發(fā)編程示例(六):等待線程執(zhí)行終止
這篇文章主要介紹了Java并發(fā)編程示例(六):等待線程執(zhí)行終止,在本節(jié),示例程序演示等待初始化方法完成后,再去執(zhí)行其他任務(wù),需要的朋友可以參考下2014-12-12
在SpringBoot中,如何使用Netty實(shí)現(xiàn)遠(yuǎn)程調(diào)用方法總結(jié)
我們?cè)谶M(jìn)行網(wǎng)絡(luò)連接的時(shí)候,建立套接字連接是一個(gè)非常消耗性能的事情,特別是在分布式的情況下,用線程池去保持多個(gè)客戶端連接,是一種非常消耗線程的行為.那么我們?cè)撏ㄟ^什么技術(shù)去解決上述的問題呢,那么就不得不提一個(gè)網(wǎng)絡(luò)連接的利器——Netty,需要的朋友可以參考下2021-06-06

