1.处理请求
过程: 1.请求首先进入到FrameworkServlet的processRequest中。
2.调用DispatcherServlet中的doService方法,对请求进行预设置,doService方法在FrameworkServlet为抽象方法。
3.最后调用DispatcherServlet的doDispatch方法,对请求进行处理,doDispatch方法为整个处理请求过程中的核心方法。
processRequest方法
/**
* FrameworkServlet中的processRequest方法
*/
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
long startTime = System.currentTimeMillis();
Throwable failureCause = null;
//获取LocaleContextHolder中的LocaleContext
LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
//获取当前请求的LocaleContext,LocaleContext为本地化信息,如zh-cn,en-us等
LocaleContext localeContext = buildLocaleContext(request);
//获取RequestContextHolder保存的RequestAttributes
RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
//获取当前请求的ServletRequestAttributes
ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);
//异步请求管理器,关于异步请求放到后面说明
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new FrameworkServlet.RequestBindingInterceptor());
//将当前请求的LocaleContext和RequestAttributes设置到LocaleContextHolder和RequestContextHolder中
initContextHolders(request, localeContext, requestAttributes);
try {
//实际请求入口,抽象方法,在DispatcherServlet中实现
doService(request, response);
}
catch (ServletException ex) {
failureCause = ex;
throw ex;
}
catch (IOException ex) {
failureCause = ex;
throw ex;
}
catch (Throwable ex) {
failureCause = ex;
throw new NestedServletException("Request processing failed", ex);
}
finally {
//恢复原来的LocaleContext和RequestAttributes到LocaleContextHolder和RequestContextHolder中
resetContextHolders(request, previousLocaleContext, previousAttributes);
if (requestAttributes != null) {
requestAttributes.requestCompleted();
}
if (logger.isDebugEnabled()) {
if (failureCause != null) {
this.logger.debug("Could not complete request", failureCause);
}
else {
if (asyncManager.isConcurrentHandlingStarted()) {
logger.debug("Leaving response open for concurrent processing");
}
else {
this.logger.debug("Successfully completed request");
}
}
}
publishRequestHandledEvent(request, startTime, failureCause);
}
}
doService方法,代码比较简单,主要做一些准备工作。
/**
* DispatcherServlet中的doService方法
* 省略注释以及日志代码
* 在处理请求之前做一些准备工作
*/
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
Map<String, Object> attributesSnapshot = null;
//判断是否是include请求,如果是的话需要对当前请求中的属性进行备份
if (WebUtils.isIncludeRequest(request)) {
attributesSnapshot = new HashMap<String, Object>();
Enumeration<?> attrNames = request.getAttributeNames();
while (attrNames.hasMoreElements()) {
String attrName = (String) attrNames.nextElement();
if (this.cleanupAfterInclude || attrName.startsWith("org.springframework.web.servlet")) {
attributesSnapshot.put(attrName, request.getAttribute(attrName));
}
}
}
//将一些组件设置到当前reuqest中,比如,springmvc容器,国际化资源解析器,主题解析器
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());
//对FlashMap进行更新
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()) {
return;
}
if (attributesSnapshot != null) {
//对request中的属性进行恢复
restoreAttributesAfterInclude(request, attributesSnapshot);
}
}
}
核心方法,doDispatch,先看一张图。
在看核心方法之前需要简单解释几个词,HandlerMapping,HandlerAdapter,ModelAndView,HandlerExecutionChain。
HandlerMapping是之前提到过的SpringMvc中的一个组件,主要是通过request找到对应处理请求的方法Handler。
HandlerAdapter 也是组件之一,作用是 使用找到的Handler处理请求。
两者的关系可以简单理解为干活的工具和干活的人。当前请求request就是要干的活,干活需要工具,那么Handler就是用来干活的工具,有了工具,那么需要一个具体的人来干活,HandlerAdapter就是干活的人。连起来就是HandlerAdapter使用Handler处理请求,或者说Handler是一个方法,HandlerAdapter就是去执行这个方法的人。
ModelAndView 比较简单易懂,处理完请求之后需要返回的视图以及传输到视图中的数据,都放在这里。
HandlerExecutionChain,意思为处理器执行链,通过HandlerMapping所找到的就是一个处理器执行链,为什么叫链,用过springmvc的都知道,在处理一个请求之前可能会执行相关的拦截器,而这个HandlerExecutionChain对象中包含了处理请求的Handler和对应的拦截器,组合到一起称之为处理器执行链。
解释了这几个东西之后,在来看相关源码。
/**
* DispatcherServlet中的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;
//使用HandlerMapping根据当前请求找到对应的方法和拦截器
mappedHandler = getHandler(processedRequest, false);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}
//根据找到的Handler获取能够执行该Handler的HandlerAdapter
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 (logger.isDebugEnabled()) {
String requestUri = urlPathHelper.getRequestUri(request);
logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);
}
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
//顺序执行所有拦截器的preHandle方法,如果某个preHandle方法值为false,那么直接return,请求结束
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
try {
//处理请求,HandlerAdapter执行Handler方法
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
}
//设置默认视图名字
applyDefaultViewName(request, mv);
//倒序执行所有拦截器的postHandle方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
//渲染视图,包括处理请求过程中出现的异常视图都在这里处理
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
//倒序执行所有拦截器的afterCompletion方法
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Error err) {
triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
return;
}
if (multipartRequestParsed) {
//如果是上传请求,清理资源
cleanupMultipart(processedRequest);
}
}
}
一个请求到这里之后就算结束了。在这个方法中几乎用到了SpringMvc中的所有组件,具体每个组件的作用以及源码在后面的文章中会做一些分析。理解处理请求的过程最好还是打断点跟一遍源码,会理解的更快。