-
客户端的所有请求都会交给前端控制器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()方法;如果出现异常,则在结果处理中被 HandlerExceptionResolver
解析异常,得到新的ModelAndView对象;
-
在返回结果处理中,由于ModelAndView的视图是逻辑视图,DispatcherServlet还要借助ViewResolver完成从逻辑视图到真实视图对象的解析工作;
-
当得到真正的View视图后,DispatcherServlet会利用模型数据ModelAndView对这个View视图对象进行渲染;
-
在返回结果处理中,视图渲染完成返回后,如果没有异常,最后倒序调用处理链中所有拦截器的afterCompletion()方法;如果有异常,则在异常处理中倒序执行所有拦截器的afterCompletion()方法。
-
客户端得到响应,可能是一个普通的HTML页面,也可以是XML或JSON字符串,还可以是一张图片或者一个PDF文件。
注:在整个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();
ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());
initContextHolders(request, localeContext, requestAttributes);
try {
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);
......
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()) {
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;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
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;
}
}
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
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()) {
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
Case2: 通过getHandler()
方法获取请求对应的处理器执行链 HandlerExecutionChain;
3)getHandler()
@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;
}
1> 获取所有HandlerMapping类型的Bean:
Spring启动时会加载五个HandlerMapping类型的Bean到IOC容器中,分别为:
- requestMappingHandlerMapping
- beanNameHandlerMapping
- routerFunctionMapping
- resourceHandlerMapping
- welcomePageHandlerMapping
其中针对HTTP GET、POST普通请求而言,我们主要看requestMappingHandlerMapping,其中包含所有注册的可以处理的请求、以及请求与相应类/方法的映射Mapping。
2> 以普通的GET、POST请求为例,通过RequestMappingHandlerMapping
获取请求对应的HandlerExecutionChain
:
getHandler()方法是如何获取到具体的HandlerExecutionChain的?
RequestMappingHandlerMapping
的继承结构:
进入到AbstractHandlerMapping
# getHandler()方法看具体的获取HandlerExecutionChain
逻辑;
@Override
@Nullable
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
Object handler = getHandlerInternal(request);
if (handler == null) {
handler = getDefaultHandler();
}
if (handler == null) {
return null;
}
if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
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:
@Override
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
request.setAttribute(LOOKUP_PATH, lookupPath);
this.mappingRegistry.acquireReadLock();
try {
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}
finally {
this.mappingRegistry.releaseReadLock();
}
}
AbstractHandlerMethodMapping
中的属性 mappingRegistry 是一个大容器:
这里内部类 MappingRegistry
中的泛型和外部类 AbstractHandlerMethodMapping<T>
的一致,由类定义 public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMethodMapping<RequestMappingInfo>
可知,这里的泛型为 RequestMappingInfo
。
这里先从请求中获取请求的路径,然后根据请求路径和请求通过lookupHandlerMethod()
方法获取HandlerMathod
;
@Nullable
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
List<Match> matches = new ArrayList<>();
List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
if (directPathMatches != null) {
addMatchingMappings(directPathMatches, matches, request);
}
if (matches.isEmpty()) {
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()
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");
}
1> 获取所有HandlerAdapter类型的Bean:
Spring启动时会加载四个HandlerAdapter类型的Bean到IOC容器中,分别为:
- RequestMappingHandlerAdapter,HTTP请求的HandlerAdapter
- HandlerFunctionAdapter
- HttpRequestHandlerAdapter
- SimpleControllerHandlerAdapter
2> 找到符合相应 HandlerMethod 的 HandlerAdapter:
HandlerAdapter#supports()方法本质上就是一个instanceof
类型判断,以RequestMappingHandlerAdapter
为例:
@Override
public boolean supports(Object handler) {
return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler)));
}
Case4: 通过 HandlerAdapter#handle() 方法开始真正执行请求;
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
的子类RequestMappingHandlerAdapter
#handlerInternal()方法:
@Override
protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ModelAndView mav;
checkRequest(request);
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session);
synchronized (mutex) {
mav = invokeHandlerMethod(request, response, handlerMethod);
}
}
else {
mav = invokeHandlerMethod(request, response, handlerMethod);
}
}
else {
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()
方法,这里触发handler中的处理方法
6)RequestMappingHandlerAdapter#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);
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 {
boolean supportsParameter(MethodParameter parameter);
@Nullable
@Nullable
Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception;
}
- 方法参数解析器argumentResolvers一共有26个:
phase2:获取返回值/结果处理器HandlerMethodReturnValueHandler;
返回值/结果处理器HandlerMethodReturnValueHandler
包含两个方法,分别为
- supportsReturnType() —> 判断返回值是否可以被当前HandlerMethodReturnValueHandler处理
- handleReturnValue() —> 处理返回值
public interface HandlerMethodReturnValueHandler {
boolean supportsReturnType(MethodParameter returnType);
void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception;
- 返回值/结果处理器一共有15个:
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;
}
}
接着看ServletInvocableHandlerMethod
#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));
}
return doInvoke(args);
}
再看doInvoke()
方法
- 通过反射、打开Controller相应方法的访问权限,进而调用相应的方法。
@Nullable
protected Object doInvoke(Object... args) throws Exception {
ReflectionUtils.makeAccessible(getBridgedMethod());
try {
return getBridgedMethod().invoke(getBean(), args);
}
catch (IllegalArgumentException ex) {
......
}
}
最后再回到 DispatcherServlet#doDispatch() 方法中,看其调用 processDispatchResult() 方法如何处理返回结果
7)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()) {
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()) {
return;
}
if (mappedHandler != null) {
mappedHandler.triggerAfterCompletion(request, response, null);
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)