首先,我们看一下DispatcherServlet的继承关系图。这里,我们着重看一下Servlet部分的继承树。下图中我们可以看到,DispatcherServlet就是实现了Servlet接口。而用来处理请求的service方法在其父类frameworkServlet中进行了重写。
其次,咱们看一下doService方法:在此方法中,除了定义了请求的属性及对应的操作外,主要是调用了doDispatch方法来处理请求的。
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
logRequest(request);
// Keep a snapshot of the request attributes in case of an include,
// to be able to restore the original attributes after the include.
Map attributesSnapshot = null;
if (WebUtils.isIncludeRequest(request)) {
attributesSnapshot = new HashMap<>();
Enumeration> attrNames = request.getAttributeNames();
while (attrNames.hasMoreElements()) {
String attrName = (String) attrNames.nextElement();
if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {
attributesSnapshot.put(attrName, request.getAttribute(attrName));
}
}
}
// Make framework objects available to handlers and 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());
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);
}
RequestPath previousRequestPath = null;
if (this.parseRequestPath) {
previousRequestPath = (RequestPath) request.getAttribute(ServletRequestPathUtils.PATH_ATTRIBUTE);
ServletRequestPathUtils.parseAndCache(request);
}
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);
}
}
if (this.parseRequestPath) {
ServletRequestPathUtils.setParsedRequestPath(previousRequestPath, request);
}
}
}
那么,咱们就着重看一下doDispatcherService是如何处理请求的,其源码如下:
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里。
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// 定义Handler适配器,负责执行Handler里面的接口或拦截器的逻辑
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
String method = request.getMethod();
boolean isGet = HttpMethod.GET.matches(method);
if (isGet || HttpMethod.HEAD.matches(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
//调用拦截器中的PreHandle方法,如果方法的返回结果为false,直接return,结束后续操作。
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 调用适配器中的handle方法,进入servlet接口方法中,对实际请求进行处理,并将返回结果赋值到视图对象中
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
//调用拦截器中的PostHandle方法
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()) {
// 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:它对处理请求的整个过程进行了监控,一旦出现异常和错误,就会激活拦截器中的afterCompletion方法,关闭所有的打开的资源,进行资源释放。(由最外层的catch代码块定义)
2:如果是文件上传的请求,在finally代码块中,进行了资源清空操作,释放所有相关资源
3:当Dispatcher接收到一个请求后,它会把请求中的URL地址的相关接口方法及拦截器封装进mappedHandler对象中。通过断点(如下图),我们可以清楚的看到mappedHandler对象中包含handler对象(即咱们请求的servlet接口方法)和interceptorList(拦截器)。其中handler对象中定义的bean和method方法,用来进行映射调用
4:Dispatcher根据mappedHandler对象中的接口方法,找到一个用来处理对应方法的适配器(HandlerAdapter)并进行封装,用来进行相应的逻辑处理。(如何映射,如何赋值 等)
5:调用拦截器中的PreHandle方法,如果方法的返回结果为false,直接return,结束后续操作。如果 返回结果为true,继续往下执行
6:调用HandlerAdapter适配器中的handle方法,进入servlet接口方法中,对实际请求进行处理,并将返回结果赋值到视图对象中
7:调用拦截器中的PostHandle方法
8:回调processDispatchResult方法,把执行结果响应给浏览器
以上就是我对DispatcherServlet大致的工作流程的理解和梳理,以供参考!



