一、Spring MVC执行流程(总结)
- 客户端的所有请求都会交给前端控制器
DispatcherServlet
来处理,DispatcherServlet
会负责调用系统的其他模块来完成用户请求的处理; - 即用户发送的请求会先从
DispatcherServlet
的doService()
方法开始;在该方法中会先将webApplicationContext、localeResolver、themeResolver等对象添加到request请求的attribute属性中,接着调用doDispatch()方法; 进入到doDispatch()方法中:
- 首先检查请求是否为文件的上传/下载请求(校验的规则是:是否是post并且contenttType是否以multipart为前缀),如果是则将请求包装成
MultipartHttpServletRequest
; - 其次调用getHandler()方法从五个HandlerMapping中找到相应的
HandlerMapping
对象(以普通HTTP请求为例,HandlerMapping为requestMappingHandlerMapping),进而获取到该Handler对应的处理链HandlerExecutionChain
对象; - 其实在获取
HandlerExecutionChain
时,其内部也获取到了Spring自带的以及我们自定义的MVC拦截器; - 然后通过上面获取到的
HandlerExecutionChain
对象,进而从四个HandlerAdapter
中获取相应的HandlerAdapter
处理器适配器(HandlerAdapter是一个适配器,它用统一的接口对各种Handler中的方法进行调用)。 - 执行处理链
HandlerExecutionChain
中全部拦截器的preHandle()方法,如果返回FALSE,则执行处理链中所有拦截器的afterCompletion()方法并立即返回。 - 接着调用
handlerAdapter
对象的handle()
方法来执行Controller中的方法;1> 其中会获取26个参数解析器
HandlerMethodArgumentResolver
,15个返回值处理器HandlerMethodReturnValueHandler
;2> 最后通过反射,打开Controller相应方法的访问权限,进而调用相应的方法;
- HandlerAdapter执行完,返回一个ModelAndView给DispatcherServlet;并执行拦截器的postHandle()方法;如果出现异常,则有HandlerExceptionHandler处理异常,得到新的ModelAndView对象;
- 由于ModelAndView的视图是逻辑视图,DispatcherServlet还要借助ViewResolver完成从逻辑视图到真实视图对象的解析工作;
- 当得到真正的View视图后,DispatcherServlet会利用这个View视图对象对模型数据ModelAndView进行渲染;
- 调用处理链中所有拦截器的afterCompletion()方法;
- 客户端得到响应,可能是一个普通的HTML页面,也可以是XML或JSON字符串,还可以是一张图片或者一个PDF文件。
- 首先检查请求是否为文件的上传/下载请求(校验的规则是:是否是post并且contenttType是否以multipart为前缀),如果是则将请求包装成
注:在整个SpringMVC的执行流程中,大量使用了模板方法,比如:HandlerAdapter#handle()方法(具体的handleInternal()逻辑由子类实现),FrameServlet#processRequest()方法(具体的doService()逻辑由子类实现)
以GET请求为例:
@RestController
public class TestController {
@GetMapping("/hello")
public String hello() {
return "hello";
}
}
二、源码分析请求映射原理/执行流程
HTTP请求的入口为DispatcherServlet,DispatcherServlet
继承自FrameworkServlet
,在FrameworkServlet
的doGet()方法便是GET请求的入口。
无论是doGet()、doPost()、doPut()、doDelete()都会进入到processRequest(request, response)
方法处理请求。
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
long startTime = System.currentTimeMillis();
Throwable failureCause = null;
// 构建语言环境
LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
LocaleContext localeContext = buildLocaleContext(request);
// 从请求中获取参数
RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
// 从servlet中构建参数
ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);
// 构建web异步管理器
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());
// 初始化上下文信息
initContextHolders(request, localeContext, requestAttributes);
try {
// 决定一个请求过来应该找到哪个Controller
doService(request, response);
}
catch (ServletException | IOException ex) {
failureCause = ex;
throw ex;
}
catch (Throwable ex) {
failureCause = ex;
throw new NestedServletException("Request processing failed", ex);
}
finally {
resetContextHolders(request, previousLocaleContext, previousAttributes);
if (requestAttributes != null) {
requestAttributes.requestCompleted();
}
logResult(request, response, failureCause, asyncManager);
publishRequestHandledEvent(request, response, startTime, failureCause);
}
}
由于FrameworkServlet
的doService()
是一个抽象方法(这样看processRequest()也是用了模板方法设计模式),我们去DispatcherServlet
中看具体的实现
1)doService()
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
logRequest(request);
// request请求添加属性
......
// 将请求的跳转信息保存起来(Controller的return是return到一个接口)
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 {
/**
* 真正分发请求的地方
*/
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);
}
}
}
}
接着进入到doDispatch(request, response)
方法,看它是怎么分派的?
2)doDispatch()
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
// web异步处理管理类
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
// 定义最后返回的ModelAndView视图
ModelAndView mv = null;
Exception dispatchException = null;
try {
// Case1、检查请求是否为上传/下载请求
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// Case2、从handlerMappings中获取请求对应的处理器执行链HandlerExecutionChain
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// Case3、 从handlerAdapters中获取请求的适配器`HandlerAdapter`
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
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;
}
}
// 执行HandlerExecutionHandler处理链中拦截器的preHandle()方法,如果返回false,则执行afterCompletion()方法并立即返回
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Case1--Case3都为准备阶段
// Case4、真正执行请求适配器HandlerAdapter
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
// 执行HandlerExecutionHandler处理链中拦截器的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);
}
// 对发送结果进行处理
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);
}
}
}
}
Case1:判断是否为上传/下载请求:
以普通的GET请求为例,判断出不是上传/下载请求;
Case2: 通过getHandler()
方法获取请求对应的处理器执行链HandlerExecutionChain;
3)getHandler()
@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
// 在Spring初始化的时候会加载所有的handlerMappings
if (this.handlerMappings != null) {
for (HandlerMapping mapping : this.handlerMappings) {
// 获取请求对应的HandlerExecutionChain
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
1> 获取所有HandlerMapping类型的Bean:
Spring启动时会加载五个HandlerMapping类型的Bean到IOC容器中,分别为:
- requestMappingHandlerMapping,请求处理器
- beanNameHandlerMapping
- routerFunctionMapping
- resourceHandlerMapping
- welcomePageHandlerMapping
其中针对HTTP GET、POST普通请求而言,我们主要看requestMappingHandlerMapping,其中包含所有注册的可以处理请求、以及请求和相应类/方法的映射Mapping。
2> 以普通的GET、POST请求为例,通过requestMappingHandlerMapping
获取请求对应的HandlerExecutionChain
:
getHandler()方法是如何获取到具体的HandlerExecutionChain的?
进入到AbstractHandlerMapping
# getHandler()方法看具体的获取HandlerExecutionChain
逻辑;
/**
* 在AbstractHandlerMapping类中
*/
@Override
@Nullable
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
// 1、获取请求对应的HandlerMethod
Object handler = getHandlerInternal(request);
if (handler == null) {
handler = getDefaultHandler();
}
if (handler == null) {
return null;
}
// Bean name or resolved handler?
if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
// 2、获取请求对应的HandlerExecutionChain(默认添加两个拦截器)
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
if (logger.isTraceEnabled()) {
logger.trace("Mapped to " + handler);
}
else if (logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) {
logger.debug("Mapped to " + executionChain.getHandler());
}
if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) {
CorsConfiguration config = (this.corsConfigurationSource != null ? this.corsConfigurationSource.getCorsConfiguration(request) : null);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
config = (config != null ? config.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
return executionChain;
}
1> 获取请求对应的HandlerMethod:
/**
* AbstractHandlerMethodMapping#getHandlerInternal()方法
*/
@Override
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
// 从请求中获取请求的路径
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
request.setAttribute(LOOKUP_PATH, lookupPath);
this.mappingRegistry.acquireReadLock();
try {
// 根据请求路径查找相应的HandlerMethod
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}
finally {
this.mappingRegistry.releaseReadLock();
}
}
先从请求中获取请求的路径,然后根据请求路径和请求通过lookupHandlerMethod()
方法获取HandlerMathod
;
@Nullable
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
List<Match> matches = new ArrayList<>();
// 从mappingRegistry的urlLookup中根据urlPath获取匹配的请求路径
List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
if (directPathMatches != null) {
// 找到匹配的请求路径,则添加到matches集合中
addMatchingMappings(directPathMatches, matches, request);
}
if (matches.isEmpty()) {
// No choice but to go through all mappings...
addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
}
if (!matches.isEmpty()) {
Match bestMatch = matches.get(0);
if (matches.size() > 1) {
Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
matches.sort(comparator);
bestMatch = matches.get(0);
if (logger.isTraceEnabled()) {
logger.trace(matches.size() + " matching mappings: " + matches);
}
if (CorsUtils.isPreFlightRequest(request)) {
return PREFLIGHT_AMBIGUOUS_MATCH;
}
Match secondBestMatch = matches.get(1);
if (comparator.compare(bestMatch, secondBestMatch) == 0) {
Method m1 = bestMatch.handlerMethod.getMethod();
Method m2 = secondBestMatch.handlerMethod.getMethod();
String uri = request.getRequestURI();
throw new IllegalStateException(
"Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}");
}
}
request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod);
handleMatch(bestMatch.mapping, lookupPath, request);
return bestMatch.handlerMethod;
}
else {
return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
}
}
phase1:从mappingRegistry的urlLookup中根据urlPath获取匹配的请求路径(this.mappingRegistry.getMappingsByUrl(lookupPath)
):
public List<T> getMappingsByUrl(String urlPath) {
return this.urlLookup.get(urlPath);
}
phase2:如果获取到多个HandlerMethod,从所有匹配的HandlerMethod中找出一个最匹配的(bestMatch)
2> 获取请求对应的执行链HandlerExecutionChain
(默认添加两个拦截器):
也就是添加一些拦截器对请求执行过滤、拦截。
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, LOOKUP_PATH);
for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
if (interceptor instanceof MappedInterceptor) {
MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
}
else {
chain.addInterceptor(interceptor);
}
}
return chain;
}
其中默认添加两个拦截器:
- ConversionServiceExposingInterceptor
- ResourceUrlProviderExposingInterceptor
Case3: 获取完请求对应的HandlerExecutionChain
之后,通过getHandlerAdapter()
进一步获取请求的适配器HandlerAdapter
;
4)getHandlerAdapter()
对于HTTP请求而言,HandlerAdapter就是HttpRequestHandlerAdapter
;
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
// 1、获取所有HandlerAdapter类型的bean
for (HandlerAdapter adapter : this.handlerAdapters) {
// 找到具体HandlerAdapter
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");
}
1> 获取所有HandlerAdapter类型的Bean:
Spring启动时会加载四个HandlerAdapter类型的Bean到IOC容器中,分别为:
- RequestMappingHandlerAdapter,HTTP请求的HandlerAdapter
- HandlerFunctionAdapter
- HttpRequestHandlerAdapter
- SimpleControllerHandlerAdapter
2> 找到符合相应HandlerMethod的HandlerAdapter:
HandlerAdapter#supports()方法本质上就是一个instanceof
类型判断,以HttpRequestHandlerAdapter
为例:
public class HttpRequestHandlerAdapter implements HandlerAdapter {
@Override
public boolean supports(Object handler) {
return (handler instanceof HttpRequestHandler);
}
.....
}
Case4: 通过HandlerAdapter#handle()方法开始真正执行相应的HandlerAdapter
;
5)HandlerAdapter#handle()
进入到AbstractHandlerMethodAdapter#handle()
方法
@Override
@Nullable
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return handleInternal(request, response, (HandlerMethod) handler);
}
这里AbstractHandlerMethodAdapter#handleInternal()
又是一个抽象方法,即其上层handle()
方法是一个模板方法
@Nullable
protected abstract ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception;
对于HTTP请求,会进入到AbstractHandlerMethodAdapter
的子类RequestHandlerMethodAdapter
#handlerInternal()方法:
@Override
protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ModelAndView mav;
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 {
// 真正执行适配器adapter的方法
// No synchronization on session demanded at all...
mav = invokeHandlerMethod(request, response, handlerMethod);
}
if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
}
else {
prepareResponse(response);
}
}
return mav;
}
进入到invokeHandlerMethod()
方法,看看Spring MVC是如何执行适配器HandlerAdapter的方法的?
6)RequestHandlerMethodAdapter#invokeHandlerMethod()
@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);
ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
// 解析请求的参数,参数解析器HandlerMethodArgumentResolverComposite有26个
if (this.argumentResolvers != null) {
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
}
// 返回值处理器
if (this.returnValueHandlers != null) {
invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
}
// 一堆赋值操作
.....
// 调用方法,然后执行
invocableMethod.invokeAndHandle(webRequest, mavContainer);
if (asyncManager.isConcurrentHandlingStarted()) {
return null;
}
return getModelAndView(mavContainer, modelFactory, webRequest);
}
finally {
webRequest.requestCompleted();
}
}
phase1:获取参数解析器HandlerMethodArgumentResolver;
参数解析器HandlerMethodArgumentResolver
- 包含两个方法,分别为
- supportsParameter() ---> 判断响应方法参数parameter是否可以被当前HandlerMethodArgumentResolver解析?
- resolveArgument() ---> 进行方法参数解析
public interface HandlerMethodArgumentResolver {
// 判断parameter是不是xxArgumentResolver可以解析的
boolean supportsParameter(MethodParameter parameter);
@Nullable
// 方法参数解析的主要逻辑
@Nullable
Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception;
}
- 方法参数解析器argumentResolvers一共有26个:
0 = {RequestParamMethodArgumentResolver@6374}
1 = {RequestParamMapMethodArgumentResolver@6375}
2 = {PathVariableMethodArgumentResolver@6376}
3 = {PathVariableMapMethodArgumentResolver@6377}
4 = {MatrixVariableMethodArgumentResolver@6378}
5 = {MatrixVariableMapMethodArgumentResolver@6379}
6 = {ServletModelAttributeMethodProcessor@6380}
7 = {RequestResponseBodyMethodProcessor@6381}
8 = {RequestPartMethodArgumentResolver@6382}
9 = {RequestHeaderMethodArgumentResolver@6383}
10 = {RequestHeaderMapMethodArgumentResolver@6384}
11 = {ServletCookieValueMethodArgumentResolver@6385}
12 = {ExpressionValueMethodArgumentResolver@6386}
13 = {SessionAttributeMethodArgumentResolver@6387}
14 = {RequestAttributeMethodArgumentResolver@6388}
15 = {ServletRequestMethodArgumentResolver@6389}
16 = {ServletResponseMethodArgumentResolver@6390}
17 = {HttpEntityMethodProcessor@6391}
18 = {RedirectAttributesMethodArgumentResolver@6392}
19 = {ModelMethodProcessor@6393}
20 = {MapMethodProcessor@6394}
21 = {ErrorsMethodArgumentResolver@6395}
22 = {SessionStatusMethodArgumentResolver@6396}
23 = {UriComponentsBuilderMethodArgumentResolver@6397}
24 = {RequestParamMethodArgumentResolver@6398}
25 = {ServletModelAttributeMethodProcessor@6399}
phase2:获取返回值/结果处理器HandlerMethodReturnValueHandler;
返回值/结果处理器HandlerMethodReturnValueHandler
- 包含两个方法,分别为
- supportsReturnType() ---> 判断响应方法放回值是否可以被当前HandlerMethodReturnValueHandler处理?
- handleReturnValue() ---> 进行返回值处理
public interface HandlerMethodReturnValueHandler {
//xxMethodReturnValueHandler是否能处理这个returnType
boolean supportsReturnType(MethodParameter returnType);
// 处理返回值
void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception;
- 返回值/结果处理器一共有15个:
0 = {ModelAndViewMethodReturnValueHandler@6417}
1 = {ModelMethodProcessor@6418}
2 = {ViewMethodReturnValueHandler@6419}
3 = {ResponseBodyEmitterReturnValueHandler@6420}
4 = {StreamingResponseBodyReturnValueHandler@6421}
5 = {HttpEntityMethodProcessor@6422}
6 = {HttpHeadersReturnValueHandler@6423}
7 = {CallableMethodReturnValueHandler@6424}
8 = {DeferredResultMethodReturnValueHandler@6425}
9 = {AsyncTaskMethodReturnValueHandler@6426}
10 = {ModelAttributeMethodProcessor@6427}
11 = {RequestResponseBodyMethodProcessor@6428}
12 = {ViewNameMethodReturnValueHandler@6429}
13 = {MapMethodProcessor@6430}
phase3:执行方法;
进入到ServletInvocableHandlerMethod
#invokeAndHandle(webRequest, mavContainer)
方法;
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;
}
}
再进入到InvocableHandlerMethod
#invokeForRequest()
看是如何处理请求的?
@Nullable
public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
// 获取方法的入参
Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
if (logger.isTraceEnabled()) {
logger.trace("Arguments: " + Arrays.toString(args));
}
// 调用真正的Controller
return doInvoke(args);
}
再看doInvoke()
方法如何执行?
- 通过反射、打开Controller相应方法的访问权限,进而调用相应的方法。
@Nullable
protected Object doInvoke(Object... args) throws Exception {
// 获得被桥接的⽅法(如果是桥接方法,则返回被桥接的方法,否则直接返回 getMethod()),然后打开访问权限
ReflectionUtils.makeAccessible(getBridgedMethod());
try {
// 通过反射,调⽤Controller中相应的⽅法
return getBridgedMethod().invoke(getBean(), args);
}
catch (IllegalArgumentException ex) {
......
}
}
最后再回到DispatcherServlet#doDispatch()方法中,看其调用processDispatchResult()方法如何处理返回结果?
processDispatchResult()
这里会进行异常的处理、视图的渲染、以及HandlerAdapter中所有拦截器的afterCompletion()方法。
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);
}
}
/** 处理程序是否返回要渲染的视图? */
if (mv != null && !mv.wasCleared()) {
/** 进行视图渲染 */
// eg3:
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;
}
// 执行HandlerExecutionChain中拦截器的afterCompletion()方法
if (mappedHandler != null) {
mappedHandler.triggerAfterCompletion(request, response, null);
}
}