本文介绍DispatcherServlet对请求的处理流程。基于Spring 4.2.2。
向DispatcherServlet发起get或post请求时,会交给DispathcerServlet的doGet和doPost方法处理,这两个方法把请求又统一交给processRequest(继承自FrameworkServlet)方法处理。
processRequest方法的关键代码:
protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
long startTime = System.currentTimeMillis();
Throwable failureCause = null;
//获得和当前线程相关的LocaleContext,如果没有返回null
LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
//为request创建一个LocaleContext实例,将request的primary locale作为当前的locale;
LocaleContext localeContext = buildLocaleContext(request);
//返回绑定到当前线程的RequestAttributes
RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
//为当前request创建ServletRequestAttributes
ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);
//把根据当前request创建的LocaleContext和RequestAttributes绑定到当前线程;
initContextHolders(request, localeContext, requestAttributes);
try{
doService(request, response);
}finally {
//请求处理结束后,恢复线程到原始状态,恢复LocaleContext和RequestAttributes;
resetContextHolders(request, previousLocaleContext, previousAttributes);
if (requestAttributes != null) {
requestAttributes.requestCompleted();
}
//请求处理结束后,发布事件通知
publishRequestHandledEvent(request, response, startTime, failureCause);
}
}
接下来跟进doService方法。doService方法的关键代码:
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
//将框架级的Object放到request中,使得对于handler和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());
//获取一个之前的request存储的且和当前request匹配的FlashMap,然后把它从存储中移除,并且移除其他已过期的FlashMap实例;
FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
if (inputFlashMap != null) {
//将inputFlashMap的只读视图放置到request;
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);
doDispatch(request, response);
}
doService主要做了准备工作,把一些接下来要用到的实例放到了request中,比如,localeResolver、themeResolver、flashmap。
继续跟进doDispatch方法。
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
//如果request是multipart类型(request.getContentType()的值以multipart/开始的),就把request转换为MultipartHttpServletRequest类型的request;
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// 为当前的request获取Handler
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
//找不到对应的Handler,就像返回404错误;
noHandlerFound(processedRequest, response);
return;
}
// 为当前request找到匹配的HandlerAdapter
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
//请求已注册interceptor的preHandle方法;
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 实际调用handler,返回ModelAndView
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
//如果Handler没有返回View对象,需要借助ViewNameTranslator接口的getViewName方法来获取一个逻辑视图名;
applyDefaultViewName(processedRequest, mv);
//请求已注册interceptor的postHandle方法;
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
//处理调用handler返回的结果:一个ModelAndView,或者是需要转化为一个ModelAndView的Exception
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Error err) {
triggerAfterCompletionWithError(processedRequest, response, mappedHandler, 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);
}
}
}
}
把这个方法中的关键点拿出来分析。
1)mappedHandler = getHandler(processedRequest);
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//按顺序遍历已加载的实现了HandlerMapping接口的bean,如果某个handlerMapping可以用request返回Handler,遍历结束;
for (HandlerMapping hm : this.handlerMappings) {
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
return handler;
}
}
return null;
}
handlerMapping是如何根据request获取到对应的handler?Handler和HandlerExecutionChain又是什么关系?
以org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping为例,因为以@RequestMapping标注的方法主要使用这个handlerMapping来寻找handler。它的getHandler()方法继承自AbstractHandlerMapping(final修饰)。
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
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 = getApplicationContext().getBean(handlerName);
}
//为handler构建一个HandlerExectionChain实例,这个实例将加入可用的interceptor; HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
return executionChain;
}
getHandlerInternal(request)方法在AbstractHandlerMapping定义为抽象方法,由RequestMappingHandlerMapping的父类AbstractHandlerMethodMapping负责实现。
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
this.mappingRegistry.acquireReadLock();
try {
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}
finally {
this.mappingRegistry.releaseReadLock();
}
}
跟进lookupHandlerMethod(lookupPath, request)方法:
//Look up the best-matching handler method for the current request.
//If multiple matches are found, the best match is selected.
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
List<Match> matches = new ArrayList<Match>();
//Return matches for the given URL path. Not thread-safe.
List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
if (directPathMatches != null) {
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()) {
Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
Collections.sort(matches, comparator);
if (logger.isTraceEnabled()) {
logger.trace("Found " + matches.size() + " matching mapping(s) for [" +
lookupPath + "] : " + matches);
}
Match bestMatch = matches.get(0);
if (matches.size() > 1) {
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();
throw new IllegalStateException("Ambiguous handler methods mapped for HTTP path '" +
request.getRequestURL() + "': {" + m1 + ", " + m2 + "}");
}
}
handleMatch(bestMatch.mapping, lookupPath, request);
return bestMatch.handlerMethod;
}
else {
return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
}
}
getMappingsByUrl方法:
public List<T> getMappingsByUrl(String urlPath) {
return this.urlLookup.get(urlPath);
}
其中this.urlLookup是LinkedMultiValueMap< String, T>类型,里面存储的内容是key-value对(以下内容为示例)
{/admin/getUserName=[{[/admin/getUserName]}], /admin/{id}/getRightNavs=[{[/admin/{id}/getRightNavs]}]}
遍历所有映射:
private void addMatchingMappings(Collection<T> mappings, List<Match> matches, HttpServletRequest request) {
for (T mapping : mappings) {
T match = getMatchingMapping(mapping, request);
if (match != null) {
matches.add(new Match(match, this.mappingRegistry.getMappings().get(mapping)));
}
}
}
不再继续跟进了,总之根据url获取到要调用的某个类的某个方法,以后有时间再跟进。
2)HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
for (HandlerAdapter ha : this.handlerAdapters) {
if (ha.supports(handler)) {
return ha;
}
}
}
对已加载的实现了HandlerAdapter接口的bean遍历,直到某个handlerAdapter匹配。默认加载三个handlerAdapter:
RequestMappingHandlerAdapter;
HttpRequestHandlerAdapter;
SimpleControllerHandlerAdapter;
Debug跟进代码,发现排在第一位的RequestMappingHandlerAdapter就可以support,所以就返回了RequestMappingHandlerAdapter。
3)processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
参考: http://blog.csdn.net/u012006689/article/details/51183615