当一个http请求过来了首先经过的是DispatcherServlet这么一个前端控制器并调用了这个前端控制器的doService方法。这个方法最终我们发现它调用了doDispatcher这么一个方法。这就是SpringMVC处理http请求的入口了。
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
if(this.logger.isDebugEnabled()) {
String attributesSnapshot = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult()?" resumed":"";
this.logger.debug("DispatcherServlet with name \'" + this.getServletName() + "\'" + attributesSnapshot + " processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");
}
HashMap attributesSnapshot1 = null;
if(WebUtils.isIncludeRequest(request)) {
attributesSnapshot1 = new HashMap();
Enumeration inputFlashMap = request.getAttributeNames();
label112:
while(true) {
String attrName;
do {
if(!inputFlashMap.hasMoreElements()) {
break label112;
}
attrName = (String)inputFlashMap.nextElement();
} while(!this.cleanupAfterInclude && !attrName.startsWith("org.springframework.web.servlet"));
attributesSnapshot1.put(attrName, request.getAttribute(attrName));
}
}
request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.getWebApplicationContext());
request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
request.setAttribute(THEME_SOURCE_ATTRIBUTE, this.getThemeSource());
if(this.flashMapManager != null) {
FlashMap inputFlashMap1 = this.flashMapManager.retrieveAndUpdate(request, response);
if(inputFlashMap1 != null) {
request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap1));
}
request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
}
try {
this.doDispatch(request, response);
} finally {
if(!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted() && attributesSnapshot1 != null) {
this.restoreAttributesAfterInclude(request, attributesSnapshot1);
}
}
}
这个方法里面我们发现定义了一个ModelAndView将要返回的视图与数据,并且首先检测这个请求是不是一个上传的请求,然后根据这个请求获取对应的Handler,如果Handler不为空的话就根据这个handler获取对应的HandlerAdapter。接着调用拦截器链的所有前置拦截的这么一个方法,接着调用adapter的真正的处理方法处理请求,最后调用拦截器链中的所有后置拦截方法。
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
try {
//定义一个空的ModelAndView
ModelAndView err = null;
Object dispatchException = null;
try {
//检查是否是上传请求
processedRequest = this.checkMultipart(request);
multipartRequestParsed = processedRequest != request;
//获取handler
mappedHandler = this.getHandler(processedRequest);
if(mappedHandler == null) {
this.noHandlerFound(processedRequest, response);
return;
}
//根据handler获取handlerAdapter
HandlerAdapter err1 = this.getHandlerAdapter(mappedHandler.getHandler());
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if(isGet || "HEAD".equals(method)) {
long lastModified = err1.getLastModified(request, mappedHandler.getHandler());
if(this.logger.isDebugEnabled()) {
this.logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
}
if((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
return;
}
}
//前置拦截
if(!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
//真正处理
err = err1.handle(processedRequest, response, mappedHandler.getHandler());
if(asyncManager.isConcurrentHandlingStarted()) {
return;
}
this.applyDefaultViewName(processedRequest, err);
//后置拦截
mappedHandler.applyPostHandle(processedRequest, response, err);
}
//后面一些catch finally语句省略。。。。。
继续跟进这个getHandler方法看看具体是怎么实现的,发现就是循环遍历最开始初始化DispatcherServlet的时候初始化的那7个handlerMapping,去调用这些handlerMapping的getHandler方法;这里我们主要看这个RequestMappingHandlerMapping。
跟进发现是调用了RequestMappingHandlerMapping的父类AbstractHandlerMapping中的getHandler方法,并且这个方法又是去调用了getHandlerInternal来获取Handler的。
继续跟进这个getHandlerInternal方法,首先它根据这个request获取它的URI,接着通过uri获取对应的HandlerMethod对象最终返回了。
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
String lookupPath = this.getUrlPathHelper().getLookupPathForRequest(request);
if(this.logger.isDebugEnabled()) {
this.logger.debug("Looking up handler method for path " + lookupPath);
}
this.mappingRegistry.acquireReadLock();
HandlerMethod var4;
try {
HandlerMethod handlerMethod = this.lookupHandlerMethod(lookupPath, request);
if(this.logger.isDebugEnabled()) {
if(handlerMethod != null) {
this.logger.debug("Returning handler method [" + handlerMethod + "]");
} else {
this.logger.debug("Did not find handler method for [" + lookupPath + "]");
}
}
var4 = handlerMethod != null?handlerMethod.createWithResolvedBean():null;
} finally {
this.mappingRegistry.releaseReadLock();
}
return var4;
}
跟进这个getLookupPathForRequest发现又调用了getPathWithinServletMapping方法。
这里我们就知道了这个lookupPath得到的就是这个请求的URI,拿到了这个URI接着就去调用lookupHandlerMethod方法了。
这里lookupHandlerMethod方法顾名思义就是通过这个URI根据请求的URI去寻找对应的HandlerMethod。
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
ArrayList matches = new ArrayList();
//通过这个uri去Map中查询与那个HandlerMethod映射
List directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
if(directPathMatches != null) {
this.addMatchingMappings(directPathMatches, matches, request);
}
if(matches.isEmpty()) {
this.addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
}
//若查询出这个uri有对应的映射关系
if(!matches.isEmpty()) {
AbstractHandlerMethodMapping.MatchComparator comparator = new AbstractHandlerMethodMapping.MatchComparator(this.getMappingComparator(request));
//对映射关系排序
matches.sort(comparator);
if(this.logger.isTraceEnabled()) {
this.logger.trace("Found " + matches.size() + " matching mapping(s) for [" + lookupPath + "] : " + matches);
}
//获取排序后第一个HandlerMethod
AbstractHandlerMethodMapping.Match bestMatch = (AbstractHandlerMethodMapping.Match)matches.get(0);
if(matches.size() > 1) {
if(CorsUtils.isPreFlightRequest(request)) {
return PREFLIGHT_AMBIGUOUS_MATCH;
}
AbstractHandlerMethodMapping.Match secondBestMatch = (AbstractHandlerMethodMapping.Match)matches.get(1);
if(comparator.compare(bestMatch, secondBestMatch) == 0) {
Method m1 = bestMatch.handlerMethod.getMethod();
Method m2 = secondBestMatch.handlerMethod.getMethod();
throw new IllegalStateException("Ambiguous handler methods mapped for HTTP path \'" + request.getRequestURL() + "\': {" + m1 + ", " + m2 + "}");
}
}
this.handleMatch(bestMatch.mapping, lookupPath, request);
return bestMatch.handlerMethod;
} else {
return this.handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
}
}
最终得到了这么一个包含了Handler与这个URI具体处理方法的一个HandlerMethod对象。注意现在这个handler可能还没有被创建出来或者说没有得到,只是知道它的beanName。最终还要调用这么一个createWithResolvedBean方法来得到。
获得了这个handler之后,又继续根据这个handler获得了HandlerExecutionChain。
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
Object handler = this.getHandlerInternal(request);
if(handler == null) {
handler = this.getDefaultHandler();
}
if(handler == null) {
return null;
} else {
if(handler instanceof String) {
String executionChain = (String)handler;
handler = this.obtainApplicationContext().getBean(executionChain);
}
HandlerExecutionChain executionChain1 = this.getHandlerExecutionChain(handler, request);
if(CorsUtils.isCorsRequest(request)) {
CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request);
CorsConfiguration handlerConfig = this.getCorsConfiguration(handler, request);
CorsConfiguration config = globalConfig != null?globalConfig.combine(handlerConfig):handlerConfig;
executionChain1 = this.getCorsHandlerExecutionChain(request, executionChain1, config);
}
return executionChain1;
}
}
所以得出最终结论getHandler这个方法最终所有通过这个URI返回了一个最开始注册的handler,然后通过 这个handler返回了一个包含这这个HandlerMethod以及一个拦截器链的这么一个对象。之后执行前置拦截器,handler方法,后置拦截,完成。