面試官:你畫的SpringMVC請(qǐng)求處理過程是從網(wǎng)上抄的吧?
閱讀本文大概需要 16?分鐘。
前言
“ 本篇使用的Spring版本為5.2.2.RELEASE ”
九大組件
/**?文件上傳解析器?*/
private?MultipartResolver?multipartResolver;
/**?區(qū)域解析器,用于國(guó)際化?*/
private?LocaleResolver?localeResolver;
/**?主題解析器?*/
private?ThemeResolver?themeResolver;
/**?Handler映射信息?*/
private?List?handlerMappings;
/**?Handler適配器*/
private?List?handlerAdapters;
/**?Handler執(zhí)行異常解析器?*/
private?List?handlerExceptionResolvers;
/**?請(qǐng)求到視圖的轉(zhuǎn)換器?*/
private?RequestToViewNameTranslator?viewNameTranslator;
/**?SpringMVC允許重定向時(shí)攜帶參數(shù),存在session中,用完就銷毀,所以叫FlashMap?*/
private?FlashMapManager?flashMapManager;
/**?視圖解析器?*/
private?List?viewResolvers;
1234567891011121314151617181920212223242526
HandlerMapping:Handler映射信息,根據(jù)請(qǐng)求攜帶的url信息查找處理器(Handler)。每個(gè)請(qǐng)求都需要對(duì)應(yīng)的Handler處理。 HandlerAdapter:Handler適配器,SpringMVC沒有直接調(diào)用處理器(Handler),而是通過HandlerAdapter來調(diào)用,主要是為了統(tǒng)一Handler的調(diào)用方式 ViewResolver:視圖解析器,用來將字符串類型的視圖名稱解析為View類型的視圖。ViewResolver需要找到渲染所用的模板和所用的技術(shù)(也就是視圖的類型)進(jìn)行渲染,具體的渲染過程則交由不同的視圖自己完成。 MultipartResolver:文件上傳解析器,主要用來處理文件上傳請(qǐng)求 HandlerExceptionResolver:Handler執(zhí)行異常解析器,用來對(duì)異常進(jìn)行統(tǒng)一處理 RequestToViewNameTranslator:請(qǐng)求到視圖的轉(zhuǎn)換器 LocaleResolver:區(qū)域解析器,用于支持國(guó)際化 FlashMapManager:SpringMVC允許重定向時(shí)攜帶參數(shù),存在session中,用完就銷毀,所以叫FlashMap ThemeResolver:主題解析器,用于支持不同的主題 九大組件中最重的的前三個(gè),HandlerMapping、HandlerAdapter和ViewResolver,因?yàn)檫@是閱讀源碼時(shí),避不開的三個(gè)組件。
調(diào)試準(zhǔn)備
@Controller
public?class?IndexController?{
????@RequestMapping("/index/home")
????public?String?home(String?id,?Student?student,?@RequestParam("code")?String?code)?{
????????System.out.println(student.getName());
????????return?"index";
????}
????@ResponseBody
????@RequestMapping("/index/list")
????public?String?list()?{
????????return?"success";
????}
}
public?class?Student?{
????private?String?name;
????private?Integer?gender;
???//?getter、setter
}
核心方法
/**
?*?Exposes?the?DispatcherServlet-specific?request?attributes?and?delegates?to?{@link?#doDispatch}
?*?for?the?actual?dispatching.
?*/
@Override
protected?void?doService(HttpServletRequest?request,?HttpServletResponse?response)?throws?Exception?{
?logRequest(request);
?//?Keep?a?snapshot?of?the?request?attributes?in?case?of?an?include,
?//?to?be?able?to?restore?the?original?attributes?after?the?include.
?Map?attributesSnapshot?=?null;
?if?(WebUtils.isIncludeRequest(request))?{
??attributesSnapshot?=?new?HashMap<>();
??Enumeration>?attrNames?=?request.getAttributeNames();
??while?(attrNames.hasMoreElements())?{
???String?attrName?=?(String)?attrNames.nextElement();
???if?(this.cleanupAfterInclude?||?attrName.startsWith(DEFAULT_STRATEGIES_PREFIX))?{
????attributesSnapshot.put(attrName,?request.getAttribute(attrName));
???}
??}
?}
?//?Make?framework?objects?available?to?handlers?and?view?objects.
?request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE,?getWebApplicationContext());
?request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE,?this.localeResolver);
?request.setAttribute(THEME_RESOLVER_ATTRIBUTE,?this.themeResolver);
?request.setAttribute(THEME_SOURCE_ATTRIBUTE,?getThemeSource());
?if?(this.flashMapManager?!=?null)?{
??FlashMap?inputFlashMap?=?this.flashMapManager.retrieveAndUpdate(request,?response);
??if?(inputFlashMap?!=?null)?{
???request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE,?Collections.unmodifiableMap(inputFlashMap));
??}
??request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE,?new?FlashMap());
??request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE,?this.flashMapManager);
?}
?try?{
??//?真正執(zhí)行的方法
??doDispatch(request,?response);
?}
?finally?{
??if?(!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted())?{
???//?Restore?the?original?attribute?snapshot,?in?case?of?an?include.
???if?(attributesSnapshot?!=?null)?{
????restoreAttributesAfterInclude(request,?attributesSnapshot);
???}
??}
?}
}
/**
?*?實(shí)際處理請(qǐng)求的方法
?*/
protected?void?doDispatch(HttpServletRequest?request,?HttpServletResponse?response)?throws?Exception?{
?HttpServletRequest?processedRequest?=?request;
?HandlerExecutionChain?mappedHandler?=?null;
?boolean?multipartRequestParsed?=?false;
?WebAsyncManager?asyncManager?=?WebAsyncUtils.getAsyncManager(request);
?try?{
??ModelAndView?mv?=?null;
??Exception?dispatchException?=?null;
??try?{
???//?校驗(yàn)是否是文件上傳請(qǐng)求
???processedRequest?=?checkMultipart(request);
???multipartRequestParsed?=?(processedRequest?!=?request);
???//?Determine?handler?for?the?current?request.
???//?為當(dāng)前請(qǐng)求找到一個(gè)合適的處理器(Handler)
???//?返回值是一個(gè)HandlerExecutionChain,也就是處理器執(zhí)行鏈
???mappedHandler?=?getHandler(processedRequest);
???if?(mappedHandler?==?null)?{
????noHandlerFound(processedRequest,?response);
????return;
???}
???//?Determine?handler?adapter?for?the?current?request.
???//?根據(jù)HandlerExecutionChain攜帶的Handler找到合適的HandlerAdapter
???HandlerAdapter?ha?=?getHandlerAdapter(mappedHandler.getHandler());
???//?Process?last-modified?header,?if?supported?by?the?handler.
???//?處理GET請(qǐng)求的緩存
???String?method?=?request.getMethod();
???boolean?isGet?=?"GET".equals(method);
???if?(isGet?||?"HEAD".equals(method))?{
????long?lastModified?=?ha.getLastModified(request,?mappedHandler.getHandler());
????if?(new?ServletWebRequest(request,?response).checkNotModified(lastModified)?&&?isGet)?{
?????return;
????}
???}
???//?執(zhí)行攔截器的preHandle方法
???if?(!mappedHandler.applyPreHandle(processedRequest,?response))?{
????return;
???}
???//?Actually?invoke?the?handler.
???//?利用HandlerAdapter來執(zhí)行Handler里對(duì)應(yīng)的處理方法
???mv?=?ha.handle(processedRequest,?response,?mappedHandler.getHandler());
???if?(asyncManager.isConcurrentHandlingStarted())?{
????return;
???}
???//?如果沒有設(shè)置視圖,則應(yīng)用默認(rèn)的視圖名
???applyDefaultViewName(processedRequest,?mv);
???//?執(zhí)行攔截器的postHandle方法
???mappedHandler.applyPostHandle(processedRequest,?response,?mv);
??}
??catch?(Exception?ex)?{
???dispatchException?=?ex;
??}
??catch?(Throwable?err)?{
???//?As?of?4.3,?we're?processing?Errors?thrown?from?handler?methods?as?well,
???//?making?them?available?for?@ExceptionHandler?methods?and?other?scenarios.
???dispatchException?=?new?NestedServletException("Handler?dispatch?failed",?err);
??}
??//?根據(jù)ModelAndView對(duì)象解析視圖
??processDispatchResult(processedRequest,?response,?mappedHandler,?mv,?dispatchException);
?}
?catch?(Exception?ex)?{
??triggerAfterCompletion(processedRequest,?response,?mappedHandler,?ex);
?}
?catch?(Throwable?err)?{
??triggerAfterCompletion(processedRequest,?response,?mappedHandler,
????new?NestedServletException("Handler?processing?failed",?err));
?}
?finally?{
??if?(asyncManager.isConcurrentHandlingStarted())?{
???//?Instead?of?postHandle?and?afterCompletion
???if?(mappedHandler?!=?null)?{
????mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest,?response);
???}
??}
??else?{
???//?Clean?up?any?resources?used?by?a?multipart?request.
???if?(multipartRequestParsed)?{
????cleanupMultipart(processedRequest);
???}
??}
?}
}
/**
?*?Return?the?HandlerExecutionChain?for?this?request.
?*?為這個(gè)request返回一個(gè)HandlerExecutionChain
?*/
@Nullable
protected?HandlerExecutionChain?getHandler(HttpServletRequest?request)?throws?Exception?{
?if?(this.handlerMappings?!=?null)?{
??for?(HandlerMapping?mapping?:?this.handlerMappings)?{
???HandlerExecutionChain?handler?=?mapping.getHandler(request);
???if?(handler?!=?null)?{
????return?handler;
???}
??}
?}
?return?null;
}

/**
??*?Return?the?HandlerAdapter?for?this?handler?object.
??*?@param?handler?the?handler?object?to?find?an?adapter?for
??*?@throws?ServletException?if?no?HandlerAdapter?can?be?found?for?the?handler.?This?is?a?fatal?error.
??*/
?protected?HandlerAdapter?getHandlerAdapter(Object?handler)?throws?ServletException?{
??if?(this.handlerAdapters?!=?null)?{
???for?(HandlerAdapter?adapter?:?this.handlerAdapters)?{
????if?(adapter.supports(handler))?{
?????return?adapter;
????}
???}
??}
??throw?new?ServletException("No?adapter?for?handler?["?+?handler?+
????"]:?The?DispatcherServlet?configuration?needs?to?include?a?HandlerAdapter?that?supports?this?handler");
?}

/**
?*?Handle?the?result?of?handler?selection?and?handler?invocation,?which?is
?*?either?a?ModelAndView?or?an?Exception?to?be?resolved?to?a?ModelAndView.
?*/
private?void?processDispatchResult(HttpServletRequest?request,?HttpServletResponse?response,
??@Nullable?HandlerExecutionChain?mappedHandler,?@Nullable?ModelAndView?mv,
??@Nullable?Exception?exception)?throws?Exception?{
?boolean?errorView?=?false;
?if?(exception?!=?null)?{
??if?(exception?instanceof?ModelAndViewDefiningException)?{
???logger.debug("ModelAndViewDefiningException?encountered",?exception);
???mv?=?((ModelAndViewDefiningException)?exception).getModelAndView();
??}
??else?{
???Object?handler?=?(mappedHandler?!=?null???mappedHandler.getHandler()?:?null);
???mv?=?processHandlerException(request,?response,?handler,?exception);
???errorView?=?(mv?!=?null);
??}
?}
?//?Did?the?handler?return?a?view?to?render?
?if?(mv?!=?null?&&?!mv.wasCleared())?{
??//?主要調(diào)用該方法渲染視圖
??render(mv,?request,?response);
??if?(errorView)?{
???WebUtils.clearErrorRequestAttributes(request);
??}
?}
?else?{
??if?(logger.isTraceEnabled())?{
???logger.trace("No?view?rendering,?null?ModelAndView?returned.");
??}
?}
?if?(WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted())?{
??//?Concurrent?handling?started?during?a?forward
??return;
?}
?if?(mappedHandler?!=?null)?{
??//?Exception?(if?any)?is?already?handled..
??mappedHandler.triggerAfterCompletion(request,?response,?null);
?}
}
/**
?*?Render?the?given?ModelAndView.
?*?This?is?the?last?stage?in?handling?a?request.?It?may?involve?resolving?the?view?by?name.
?*?@param?mv?the?ModelAndView?to?render
?*?@param?request?current?HTTP?servlet?request
?*?@param?response?current?HTTP?servlet?response
?*?@throws?ServletException?if?view?is?missing?or?cannot?be?resolved
?*?@throws?Exception?if?there's?a?problem?rendering?the?view
?*/
protected?void?render(ModelAndView?mv,?HttpServletRequest?request,?HttpServletResponse?response)?throws?Exception?{
?//?Determine?locale?for?request?and?apply?it?to?the?response.
?Locale?locale?=
???(this.localeResolver?!=?null???this.localeResolver.resolveLocale(request)?:?request.getLocale());
?response.setLocale(locale);
?View?view;
?String?viewName?=?mv.getViewName();
?if?(viewName?!=?null)?{
??//?We?need?to?resolve?the?view?name.
??//?根據(jù)給定的視圖名稱,解析獲取View對(duì)象
??view?=?resolveViewName(viewName,?mv.getModelInternal(),?locale,?request);
??if?(view?==?null)?{
???throw?new?ServletException("Could?not?resolve?view?with?name?'"?+?mv.getViewName()?+
?????"'?in?servlet?with?name?'"?+?getServletName()?+?"'");
??}
?}
?else?{
??//?No?need?to?lookup:?the?ModelAndView?object?contains?the?actual?View?object.
??view?=?mv.getView();
??if?(view?==?null)?{
???throw?new?ServletException("ModelAndView?["?+?mv?+?"]?neither?contains?a?view?name?nor?a?"?+
?????"View?object?in?servlet?with?name?'"?+?getServletName()?+?"'");
??}
?}
?//?Delegate?to?the?View?object?for?rendering.
?if?(logger.isTraceEnabled())?{
??logger.trace("Rendering?view?["?+?view?+?"]?");
?}
?try?{
??if?(mv.getStatus()?!=?null)?{
???response.setStatus(mv.getStatus().value());
??}
??view.render(mv.getModelInternal(),?request,?response);
?}
?catch?(Exception?ex)?{
??if?(logger.isDebugEnabled())?{
???logger.debug("Error?rendering?view?["?+?view?+?"]",?ex);
??}
??throw?ex;
?}
}
@Nullable
protected?View?resolveViewName(String?viewName,?@Nullable?Map?model,
??Locale?locale,?HttpServletRequest?request)?throws?Exception?{
?if?(this.viewResolvers?!=?null)?{
??for?(ViewResolver?viewResolver?:?this.viewResolvers)?{
???View?view?=?viewResolver.resolveViewName(viewName,?locale);
???if?(view?!=?null)?{
????return?view;
???}
??}
?}
?return?null;
}

"org.springframework.web.servlet.view.InternalResourceViewResolver">
?"prefix"?value="/WEB-INF/views/"?/>
?"suffix"?value=".html"?/>

“ 因?yàn)樵诰帉慍ontroller里面的方法的時(shí)候,各種類型的參數(shù)都有,SpringMVC是怎么處理不同類型的參數(shù)的呢?SpringMVC處理請(qǐng)求完成后,一定會(huì)返回ModelAndView嗎,如果加了@ResponseBody注解呢? ”
參數(shù)綁定
//?Actually?invoke?the?handler.
mv?=?ha.handle(processedRequest,?response,?mappedHandler.getHandler());
/**
?*?This?implementation?expects?the?handler?to?be?an?{@link?HandlerMethod}.
?*/
@Override
@Nullable
public?final?ModelAndView?handle(HttpServletRequest?request,?HttpServletResponse?response,?Object?handler)
??throws?Exception?{
?return?handleInternal(request,?response,?(HandlerMethod)?handler);
}
@Override
protected?ModelAndView?handleInternal(HttpServletRequest?request,
??HttpServletResponse?response,?HandlerMethod?handlerMethod)?throws?Exception?{
?ModelAndView?mav;
?//?校驗(yàn)指定的請(qǐng)求以獲取受支持的方法類型(GET、POST等)和所需的session
?checkRequest(request);
?//?Execute?invokeHandlerMethod?in?synchronized?block?if?required.
?if?(this.synchronizeOnSession)?{
??HttpSession?session?=?request.getSession(false);
??if?(session?!=?null)?{
???Object?mutex?=?WebUtils.getSessionMutex(session);
???synchronized?(mutex)?{
????mav?=?invokeHandlerMethod(request,?response,?handlerMethod);
???}
??}
??else?{
???//?No?HttpSession?available?->?no?mutex?necessary
???mav?=?invokeHandlerMethod(request,?response,?handlerMethod);
??}
?}
?else?{
??//?No?synchronization?on?session?demanded?at?all...
??//?真正執(zhí)行handler的方法
??mav?=?invokeHandlerMethod(request,?response,?handlerMethod);
?}
?if?(!response.containsHeader(HEADER_CACHE_CONTROL))?{
??if?(getSessionAttributesHandler(handlerMethod).hasSessionAttributes())?{
???applyCacheSeconds(response,?this.cacheSecondsForSessionAttributeHandlers);
??}
??else?{
???prepareResponse(response);
??}
?}
?return?mav;
}
/**
?*?Invoke?the?{@link?RequestMapping}?handler?method?preparing?a?{@link?ModelAndView}
?*?if?view?resolution?is?required.
?*?執(zhí)行@RequestMapping標(biāo)注的handler方法,如果需要解析視圖就準(zhǔn)備一個(gè)ModelAndView
?*/
@Nullable
protected?ModelAndView?invokeHandlerMethod(HttpServletRequest?request,
??HttpServletResponse?response,?HandlerMethod?handlerMethod)?throws?Exception?{
?ServletWebRequest?webRequest?=?new?ServletWebRequest(request,?response);
?try?{
??WebDataBinderFactory?binderFactory?=?getDataBinderFactory(handlerMethod);
??ModelFactory?modelFactory?=?getModelFactory(handlerMethod,?binderFactory);
??// HandlerMethod接口封裝執(zhí)行方法的信息,提供對(duì)方法參數(shù),方法返回值,方法注釋等的便捷訪問。
??ServletInvocableHandlerMethod?invocableMethod?=?createInvocableHandlerMethod(handlerMethod);
??if?(this.argumentResolvers?!=?null)?{
???invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
??}
??if?(this.returnValueHandlers?!=?null)?{
???invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
??}
??invocableMethod.setDataBinderFactory(binderFactory);
??invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
??//?ModelAndViewContainer可以看做ModelAndView的上下文容器,關(guān)聯(lián)著Model和View的信息
??ModelAndViewContainer?mavContainer?=?new?ModelAndViewContainer();
??mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
??modelFactory.initModel(webRequest,?mavContainer,?invocableMethod);
??mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
??AsyncWebRequest?asyncWebRequest?=?WebAsyncUtils.createAsyncWebRequest(request,?response);
??asyncWebRequest.setTimeout(this.asyncRequestTimeout);
??WebAsyncManager?asyncManager?=?WebAsyncUtils.getAsyncManager(request);
??asyncManager.setTaskExecutor(this.taskExecutor);
??asyncManager.setAsyncWebRequest(asyncWebRequest);
??asyncManager.registerCallableInterceptors(this.callableInterceptors);
??asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);
??if?(asyncManager.hasConcurrentResult())?{
???Object?result?=?asyncManager.getConcurrentResult();
???mavContainer?=?(ModelAndViewContainer)?asyncManager.getConcurrentResultContext()[0];
???asyncManager.clearConcurrentResult();
???LogFormatUtils.traceDebug(logger,?traceOn?->?{
????String?formatted?=?LogFormatUtils.formatValue(result,?!traceOn);
????return?"Resume?with?async?result?["?+?formatted?+?"]";
???});
???invocableMethod?=?invocableMethod.wrapConcurrentResult(result);
??}
??//?真正執(zhí)行Handler的方法
??invocableMethod.invokeAndHandle(webRequest,?mavContainer);
??if?(asyncManager.isConcurrentHandlingStarted())?{
???return?null;
??}
??//?獲取ModelAndeView對(duì)象
??return?getModelAndView(mavContainer,?modelFactory,?webRequest);
?}
?finally?{
??webRequest.requestCompleted();
?}
}
/**
?*?Invoke?the?method?and?handle?the?return?value?through?one?of?the
?*?configured?{@link?HandlerMethodReturnValueHandler?HandlerMethodReturnValueHandlers}.
?*?@param?webRequest?the?current?request
?*?@param?mavContainer?the?ModelAndViewContainer?for?this?request
?*?@param?providedArgs?"given"?arguments?matched?by?type?(not?resolved)
?*/
public?void?invokeAndHandle(ServletWebRequest?webRequest,?ModelAndViewContainer?mavContainer,
??Object...?providedArgs)?throws?Exception?{
?//?執(zhí)行handler的方法
?Object?returnValue?=?invokeForRequest(webRequest,?mavContainer,?providedArgs);
?setResponseStatus(webRequest);
?if?(returnValue?==?null)?{
??if?(isRequestNotModified(webRequest)?||?getResponseStatus()?!=?null?||?mavContainer.isRequestHandled())?{
???disableContentCachingIfNecessary(webRequest);
???mavContainer.setRequestHandled(true);
???return;
??}
?}
?else?if?(StringUtils.hasText(getResponseStatusReason()))?{
??mavContainer.setRequestHandled(true);
??return;
?}
?mavContainer.setRequestHandled(false);
?Assert.state(this.returnValueHandlers?!=?null,?"No?return?value?handlers");
?try?{
??this.returnValueHandlers.handleReturnValue(
????returnValue,?getReturnValueType(returnValue),?mavContainer,?webRequest);
?}
?catch?(Exception?ex)?{
??if?(logger.isTraceEnabled())?{
???logger.trace(formatErrorForReturnValue(returnValue),?ex);
??}
??throw?ex;
?}
}
/**
?*?Invoke?the?method?after?resolving?its?argument?values?in?the?context?of?the?given?request.
?*?Argument?values?are?commonly?resolved?through
?*?{@link?HandlerMethodArgumentResolver?HandlerMethodArgumentResolvers}.
?*?The?{@code?providedArgs}?parameter?however?may?supply?argument?values?to?be?used?directly,
?*?i.e.?without?argument?resolution.?Examples?of?provided?argument?values?include?a
?*?{@link?WebDataBinder},?a?{@link?SessionStatus},?or?a?thrown?exception?instance.
?*?Provided?argument?values?are?checked?before?argument?resolvers.
?*?Delegates?to?{@link?#getMethodArgumentValues}?and?calls?{@link?#doInvoke}?with?the
?*?resolved?arguments.
?*?@param?request?the?current?request
?*?@param?mavContainer?the?ModelAndViewContainer?for?this?request
?*?@param?providedArgs?"given"?arguments?matched?by?type,?not?resolved
?*?@return?the?raw?value?returned?by?the?invoked?method
?*?@throws?Exception?raised?if?no?suitable?argument?resolver?can?be?found,
?*?or?if?the?method?raised?an?exception
?*?@see?#getMethodArgumentValues
?*?@see?#doInvoke
?*/
@Nullable
public?Object?invokeForRequest(NativeWebRequest?request,?@Nullable?ModelAndViewContainer?mavContainer,
??Object...?providedArgs)?throws?Exception?{
?//?獲取參數(shù)
?Object[]?args?=?getMethodArgumentValues(request,?mavContainer,?providedArgs);
?if?(logger.isTraceEnabled())?{
??logger.trace("Arguments:?"?+?Arrays.toString(args));
?}
?//?執(zhí)行
?return?doInvoke(args);
}
/**
?*?Get?the?method?argument?values?for?the?current?request,?checking?the?provided
?*?argument?values?and?falling?back?to?the?configured?argument?resolvers.
?*?The?resulting?array?will?be?passed?into?{@link?#doInvoke}.
?*?@since?5.1.2
?*/
protected?Object[]?getMethodArgumentValues(NativeWebRequest?request,?@Nullable?ModelAndViewContainer?mavContainer,
??Object...?providedArgs)?throws?Exception?{
?//?獲取方法上所有的參數(shù)
?MethodParameter[]?parameters?=?getMethodParameters();
?if?(ObjectUtils.isEmpty(parameters))?{
??return?EMPTY_ARGS;
?}
?Object[]?args?=?new?Object[parameters.length];
?for?(int?i?=?0;?i???MethodParameter?parameter?=?parameters[i];
??parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
??args[i]?=?findProvidedArgument(parameter,?providedArgs);
??if?(args[i]?!=?null)?{
???continue;
??}
??if?(!this.resolvers.supportsParameter(parameter))?{
???throw?new?IllegalStateException(formatArgumentError(parameter,?"No?suitable?resolver"));
??}
??try?{
???
???args[i]?=?this.resolvers.resolveArgument(parameter,?mavContainer,?request,?this.dataBinderFactory);
??}
??catch?(Exception?ex)?{
???//?Leave?stack?trace?for?later,?exception?may?actually?be?resolved?and?handled...
???if?(logger.isDebugEnabled())?{
????String?exMsg?=?ex.getMessage();
????if?(exMsg?!=?null?&&?!exMsg.contains(parameter.getExecutable().toGenericString()))?{
?????logger.debug(formatArgumentError(parameter,?exMsg));
????}
???}
???throw?ex;
??}
?}
?return?args;
}

根據(jù)調(diào)試信息可以看到,用來處理請(qǐng)求參數(shù)的類是HandlerMethodArgumentResolver接口的實(shí)現(xiàn)類HandlerMethodArgumentResolverComposite,此時(shí)正在處理的參數(shù)是一個(gè)Student對(duì)象,并且已經(jīng)把值注綁定了,也就是說真正執(zhí)行綁定的是方法resolveArgument
resolveArgument
resolveArgument是真正執(zhí)行綁定的的方法
/**
?*?Find?a?registered?{@link?HandlerMethodArgumentResolver}?that?supports
?*?the?given?method?parameter.
?*/
@Nullable
private?HandlerMethodArgumentResolver?getArgumentResolver(MethodParameter?parameter)?{
?HandlerMethodArgumentResolver?result?=?this.argumentResolverCache.get(parameter);
?if?(result?==?null)?{
??for?(HandlerMethodArgumentResolver?resolver?:?this.argumentResolvers)?{
???if?(resolver.supportsParameter(parameter))?{
????result?=?resolver;
????this.argumentResolverCache.put(parameter,?result);
????break;
???}
??}
?}
?return?result;
}

根據(jù)博主的調(diào)試可以知道
/**
?*?Resolve?the?argument?from?the?model?or?if?not?found?instantiate?it?with
?*?its?default?if?it?is?available.?The?model?attribute?is?then?populated
?*?with?request?values?via?data?binding?and?optionally?validated
?*?if?{@[email protected]}?is?present?on?the?argument.
?*?@throws?BindException?if?data?binding?and?validation?result?in?an?error
?*?and?the?next?method?parameter?is?not?of?type?{@link?Errors}
?*?@throws?Exception?if?WebDataBinder?initialization?fails
?*/
@Override
@Nullable
public?final?Object?resolveArgument(MethodParameter?parameter,?@Nullable?ModelAndViewContainer?mavContainer,
??NativeWebRequest?webRequest,?@Nullable?WebDataBinderFactory?binderFactory)?throws?Exception?{
?Assert.state(mavContainer?!=?null,?"ModelAttributeMethodProcessor?requires?ModelAndViewContainer");
?Assert.state(binderFactory?!=?null,?"ModelAttributeMethodProcessor?requires?WebDataBinderFactory");
?//?獲取參數(shù)名
?String?name?=?ModelFactory.getNameForParameter(parameter);
?//?獲取參數(shù)上的ModelAttribute注解
?ModelAttribute?ann?=?parameter.getParameterAnnotation(ModelAttribute.class);
?if?(ann?!=?null)?{
??mavContainer.setBinding(name,?ann.binding());
?}
?Object?attribute?=?null;
?BindingResult?bindingResult?=?null;
?if?(mavContainer.containsAttribute(name))?{
??attribute?=?mavContainer.getModel().get(name);
?}
?else?{
??//?Create?attribute?instance
??try?{
???//?創(chuàng)建參數(shù)類型的實(shí)例(未注入值),底層就是通過反射調(diào)用構(gòu)造方法
???attribute?=?createAttribute(name,?parameter,?binderFactory,?webRequest);
??}
??catch?(BindException?ex)?{
???if?(isBindExceptionRequired(parameter))?{
????//?No?BindingResult?parameter?->?fail?with?BindException
????throw?ex;
???}
???//?Otherwise,?expose?null/empty?value?and?associated?BindingResult
???if?(parameter.getParameterType()?==?Optional.class)?{
????attribute?=?Optional.empty();
???}
???bindingResult?=?ex.getBindingResult();
??}
?}
?if?(bindingResult?==?null)?{
??//?Bean?property?binding?and?validation;
??//?skipped?in?case?of?binding?failure?on?construction.
??WebDataBinder?binder?=?binderFactory.createBinder(webRequest,?attribute,?name);
??if?(binder.getTarget()?!=?null)?{
???if?(!mavContainer.isBindingDisabled(name))?{
????//?真正執(zhí)行綁定(值注入)的方法
????bindRequestParameters(binder,?webRequest);
???}
???validateIfApplicable(binder,?parameter);
???if?(binder.getBindingResult().hasErrors()?&&?isBindExceptionRequired(binder,?parameter))?{
????throw?new?BindException(binder.getBindingResult());
???}
??}
??//?Value?type?adaptation,?also?covering?java.util.Optional
??if?(!parameter.getParameterType().isInstance(attribute))?{
???attribute?=?binder.convertIfNecessary(binder.getTarget(),?parameter.getParameterType(),?parameter);
??}
??bindingResult?=?binder.getBindingResult();
?}
?//?Add?resolved?attribute?and?BindingResult?at?the?end?of?the?model
?Map?bindingResultModel?=?bindingResult.getModel();
?mavContainer.removeAttributes(bindingResultModel);
?mavContainer.addAllAttributes(bindingResultModel);
?return?attribute;
}

/**
?*?This?implementation?downcasts?{@link?WebDataBinder}?to
?*?{@link?ServletRequestDataBinder}?before?binding.
?*?@see?ServletRequestDataBinderFactory
?*/
@Override
protected?void?bindRequestParameters(WebDataBinder?binder,?NativeWebRequest?request)?{
?ServletRequest?servletRequest?=?request.getNativeRequest(ServletRequest.class);
?Assert.state(servletRequest?!=?null,?"No?ServletRequest");
?ServletRequestDataBinder?servletBinder?=?(ServletRequestDataBinder)?binder;
?//?執(zhí)行綁定的方法
?servletBinder.bind(servletRequest);
}
public?void?bind(ServletRequest?request)?{
?//?獲取所有參數(shù)的鍵值對(duì)
?MutablePropertyValues?mpvs?=?new?ServletRequestParameterPropertyValues(request);
?//?處理文件上傳請(qǐng)求
?MultipartRequest?multipartRequest?=?WebUtils.getNativeRequest(request,?MultipartRequest.class);
?if?(multipartRequest?!=?null)?{
??bindMultipart(multipartRequest.getMultiFileMap(),?mpvs);
?}
?//?把url中攜帶的參數(shù)也加入到MutablePropertyValues
?addBindValues(mpvs,?request);
?//?執(zhí)行綁定(注入值)
?doBind(mpvs);
}

返回值處理
/**
?*?Invoke?the?method?and?handle?the?return?value?through?one?of?the
?*?configured?{@link?HandlerMethodReturnValueHandler?HandlerMethodReturnValueHandlers}.
?*?@param?webRequest?the?current?request
?*?@param?mavContainer?the?ModelAndViewContainer?for?this?request
?*?@param?providedArgs?"given"?arguments?matched?by?type?(not?resolved)
?*/
public?void?invokeAndHandle(ServletWebRequest?webRequest,?ModelAndViewContainer?mavContainer,
??Object...?providedArgs)?throws?Exception?{
?Object?returnValue?=?invokeForRequest(webRequest,?mavContainer,?providedArgs);
?setResponseStatus(webRequest);
?if?(returnValue?==?null)?{
??if?(isRequestNotModified(webRequest)?||?getResponseStatus()?!=?null?||?mavContainer.isRequestHandled())?{
???disableContentCachingIfNecessary(webRequest);
???mavContainer.setRequestHandled(true);
???return;
??}
?}
?else?if?(StringUtils.hasText(getResponseStatusReason()))?{
??mavContainer.setRequestHandled(true);
??return;
?}
?mavContainer.setRequestHandled(false);
?Assert.state(this.returnValueHandlers?!=?null,?"No?return?value?handlers");
?try?{
??//?真正處理不同類型返回值的方法
??this.returnValueHandlers.handleReturnValue(
????returnValue,?getReturnValueType(returnValue),?mavContainer,?webRequest);
?}
?catch?(Exception?ex)?{
??if?(logger.isTraceEnabled())?{
???logger.trace(formatErrorForReturnValue(returnValue),?ex);
??}
??throw?ex;
?}
}
/**
?*?Iterate?over?registered?{@link?HandlerMethodReturnValueHandler?HandlerMethodReturnValueHandlers}?and?invoke?the?one?that?supports?it.
?*?@throws?IllegalStateException?if?no?suitable?{@link?HandlerMethodReturnValueHandler}?is?found.
?*/
@Override
public?void?handleReturnValue(@Nullable?Object?returnValue,?MethodParameter?returnType,
??ModelAndViewContainer?mavContainer,?NativeWebRequest?webRequest)?throws?Exception?{
?//?根據(jù)返回值個(gè)返回值類型選取合適的HandlerMethodReturnValueHandler
?HandlerMethodReturnValueHandler?handler?=?selectHandler(returnValue,?returnType);
?if?(handler?==?null)?{
??throw?new?IllegalArgumentException("Unknown?return?value?type:?"?+?returnType.getParameterType().getName());
?}
?//?真正的處理返回值
?handler.handleReturnValue(returnValue,?returnType,?mavContainer,?webRequest);
}
@Nullable
private?HandlerMethodReturnValueHandler?selectHandler(@Nullable?Object?value,?MethodParameter?returnType)?{
?boolean?isAsyncValue?=?isAsyncReturnValue(value,?returnType);
?for?(HandlerMethodReturnValueHandler?handler?:?this.returnValueHandlers)?{
??if?(isAsyncValue?&&?!(handler?instanceof?AsyncHandlerMethodReturnValueHandler))?{
???continue;
??}
??if?(handler.supportsReturnType(returnType))?{
???return?handler;
??}
?}
?return?null;
}

@Override
public?void?handleReturnValue(@Nullable?Object?returnValue,?MethodParameter?returnType,
??ModelAndViewContainer?mavContainer,?NativeWebRequest?webRequest)
??throws?IOException,?HttpMediaTypeNotAcceptableException,?HttpMessageNotWritableException?{
?//?設(shè)置該請(qǐng)求是否已在處理程序中完全處理,例如@ResponseBody方法不需要視圖解析器,此處就可以設(shè)置為true。
?//?當(dāng)控制器方法聲明類型為ServletResponse或OutputStream的參數(shù)時(shí),也可以設(shè)置此標(biāo)志為true。?
?//?這個(gè)屬性設(shè)置成true之后,上層getModelAndView獲取ModelAndView時(shí)會(huì)返回Null,因?yàn)椴恍枰晥D。
?//?默認(rèn)值為false
?mavContainer.setRequestHandled(true);
?ServletServerHttpRequest?inputMessage?=?createInputMessage(webRequest);
?ServletServerHttpResponse?outputMessage?=?createOutputMessage(webRequest);
?//?Try?even?with?null?return?value.?ResponseBodyAdvice?could?get?involved.
?//?底層就是利用java.io.OutputStreamWriter類把返回值寫到網(wǎng)絡(luò)IO
?writeWithMessageConverters(returnValue,?returnType,?inputMessage,?outputMessage);
}

總結(jié)
推薦閱讀:
整理了15個(gè)好用的API接口管理免費(fèi)神器,隨便挑...
Elasticsearch 在互聯(lián)網(wǎng)公司大量真實(shí)的應(yīng)用案例
微信掃描二維碼,關(guān)注我的公眾號(hào)
朕已閱?

