在DispatcherServlet.java的doDispatch方法中,springmvc通過handlermapping裡面找哪個handler能處理請求,handler封裝了目標方法的資訊,
mappedHandler = getHandler(processedRequest);
然後為當前的handler找到一個介面卡HandlerAdapter,尋找的過程為:在DispatcherServlet.java的getHandlerAdapter方法中,挨個匹配,判斷當前adapter是否支援當前handler,判斷方法為只要handler是handlerMethod型別就生效,就支援
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
if (this.handlerAdapters != null) {
for (HandlerAdapter adapter : this.handlerAdapters) {
if (adapter.supports(handler)) {
return adapter;
}
}
}
找到介面卡以後判斷當前請求是不是「GET」方法以及「HEAD」,「HEAD」不是伺服器真正處理的
介面卡HandlerAdapter把(目標方法、request、response)傳入handle執行目標方法
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
怎麼執行目標方法:
return this.handler;
mav = invokeHandlerMethod(request,response,handlerMethod);
在RequestMappingHandlerAdapter.java的invokeHandlerMethod方法中,
為invocableMethod方法設定引數解析器argumentResolvers,引數解析器確定將要執行的目標方法的每一個引數的值是什麼
當前解析器是否支援解析這種引數
支援就呼叫 resolveArgument
為invocableMethod方法設定返回值處理器returnValueHandlers
把26個argumentResolvers和15個returnValueHandlers都放入目標方法包裝的ServletInvocableHandlerMethod中
然後真正執行目標方法的語句
invocableMethod.invokeAndHandle(WebRequest,mavContainer);
在ServletInvocableHandlerMethod.java的invokeAndHandle方法中,執行了controller
Object returnValue = invokeForRequest(webRequest,mavContainer,proviedArgs);
step into 進入InvocableHandlerMethod.java,確定目標方法每一個引數的值
Object[] agrs = getMethodArgumentValues(request,mavContainer,providerArgs)
在InvocableHandlerMethod.java的getMethodArgumentValues方法中,先獲取方法所有的引數宣告(詳細資訊)。
MethodParameter[] parameters = getMethodParameters();
判斷引數是否為空,為空則無需確定任何值直接返回;
if (ObjectUtils.isEmpty(parameters)) {
return EMPTY_ARGS;
}
如果有參數列,new一個Object[],參數列有多少個Object[]就有多長
Object[] args = new Object[parameters.length];
for (int i = 0; i < parameters.length; i++) {
MethodParameter parameter = parameters[i];
parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
args[i] = findProvidedArgument(parameter, providedArgs);
先宣告args遍歷parameters,給args[i]賦值,args[i]的值解析器解析了才有
解析之前,判斷26個解析器是不是supportsParamter支援這個引數型別。
this.resolvers.supportsParameter(parameter)
HandlerMethodArgumentResolverComposite.java的getArgumentResolver方法中
獲取一個快取result
result==null,進入增強for迴圈,逐個確定26個解析器誰能支援這種引數
當前resolver支援解析,放到快取裡邊,判斷成功,進入解析
解析引數
this.resolvers.resolveArgument
遍歷迴圈所有引數
最終返回args,args就是確定好的值
處理返回結果的時候,把mavContainer傳進去,
this.returnValueHandlers.handlerReturnValue
在handlerMethod.java的getReturnValueType方法中獲取返回的結果型別
HandlerMethodArgumentResolverComposite.java的handleReturnValue方法中,
找到返回值的處理器
如果返回值是一個字串,拿到字串然後儲存到mavContainer
返回值處理完以後,getModelAndView
目標方法執行完成
將所有的資料都放在 ModelAndViewContainer;包含要去的頁面地址View。還包含Model資料。
從ModelAndViewContainer拿到預設的Model,updateBindingResult,拿到key放到繫結裡邊,又被封裝成ModelAndView,然後返回這個新封裝的mav
處理派發結果
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
拿到所有請求域中的屬性,解析得到檢視名
渲染頁面
view.render(mv.getModelInternal(),request,response);
拿到頁面資料
createMergeOutputModel(model,request,response);
創造合併的輸出模型
如果model不等於空
mergeModel.putAll(model)//即把資料轉移到HashMap
渲染合併輸出的模型資料
renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
把上面的Hashmap傳進來了
拿到請求物件,獲取的原生的Servletrequest
return originalRequest
暴露模型作為請求域屬性
// Expose the model object as request attributes.
exposeModelAsRequestAttributes(model, request);