一、源码分析前还是需要一张流程图作为指导,如下:

二、简单介绍以及源码定位

DispatcherServlet其实就是一个HttpServlet,他是HttpServlet的子类,所以它和普通的HttpServlet在web.xml里同样的配置。

这个Servlet的doPost和doGet方法的实现是DispatcherServlet的父类FrameworkServlet中实现的,两个方法里都是调用processRequest方法。processRequest的实现是在FrameworkServlet中,此方法中最主要的操作就是调用doService方法。

doService方法的最终实现是在DispatcherServlet中,这样所有的Http请求(GET、POST、PUT和DELETE等)的最终操作就DispatcherServlet中实现了。

DispatcherServlet中doService的实现如下,对Request设置了一些全局属性,最终接下来的操作是在doDispatcher函数中实现了。

[java] view plain copy
//获取请求,设置一些request的参数,然后分发给doDispatch
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
if (logger.isDebugEnabled()) {
String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";
logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed +
" processing " + request.getMethod() + " request for [" + getRequestUri(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<String, Object> attributesSnapshot = null;
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));
}
}
} // Make framework objects available to handlers and view objects.
/* 设置web应用上下文**/
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 inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
if (inputFlashMap != null) {
request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
}
//Flash attributes 在对请求的重定向生效之前被临时存储(通常是在session)中,并且在重定向之后被立即移除
request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
//FlashMap 被用来管理 flash attributes 而 FlashMapManager 则被用来存储,获取和管理 FlashMap 实体.
request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager); 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);
}
}
}
}

doDispatch()方法源码如下:

/**
* Process the actual dispatching to the handler.
* <p>The handler will be obtained by applying the servlet's HandlerMappings in order.
* The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters
* to find the first that supports the handler class.
* <p>All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers
* themselves to decide which methods are acceptable.
* @param request current HTTP request
* @param response current HTTP response
* @throws Exception in case of any kind of processing failure
*/
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); // Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
} // Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (logger.isDebugEnabled()) {
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;
} // Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) {
return;
} applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
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. web应用服务器接收到一个新请求是,读取web.xml中的配置,如果匹配DispatcherServlet的请求映射路径,web容器将该请求转发给DispatcherServlet进行处理

2. DispatcherServlet接收到请求后,执行doDispatch方法,此方法遍历DispatcherServlet中的HandlerMapping(处理器映射器)集合,根据请求的HttpServletRequest信息通过HandlerMapping对象方法找到HandlerExecutionChain(执行链,内含拦截器和处理器)。

3. DispatcherServlet继续执行doDispatch方法,根据得到的HandlerExecutionChain(执行链)中的handler遍历自己的HandlerAdapter(处理器适配器)集合,找到支持这个Handler的HandlerAdapter并返回。

4.继续doDispatch方法,把HandlerExecutionChain(执行链)内部的那些前置拦截器逻辑都执行完,然后再再通过得到的HandlerAdapter执行HandlerExecutionChain内部的处理器,会返回一个ModelAndView包含了视图逻辑名和模型数据信息

5.调用执行链的方法,执行拦截器的后置拦截器

6. ModelAndView中包含的是“逻辑视图名”,而非真正的视图对象,DispatcherServlet借助ViewResolver完成逻辑视图名到真实视图名对象的解析工作

7. 当得到真实的视图对象View后,DispatcherServlet就使用这个View对象对ModelAndView中的模型数据进行视图渲染

8. 最终客户端得到HTML页面什么的

最新文章

  1. C语言 &#183; 4-3水仙花数
  2. 百度编辑器ueditor插入表格没有边框颜色的解决方法
  3. java12
  4. 配置 Docker 加速器(Docker Hub Mirror)
  5. 获取局域网中指定IP或是主机名称的所有文件夹及其搜索文件
  6. [慢查优化]慎用MySQL子查询,尤其是看到DEPENDENT SUBQUERY标记时
  7. toad 9.6和toad 12.1工具使用比较
  8. 关于cookie的清除
  9. javascript实现单例模式
  10. Android(java)学习笔记130:ProgressBar使用的
  11. JAVA 反序列化攻击
  12. 【二分法】 HDU 2446 Shell Pyramid
  13. 关于UI_USER_INTERFACE_IDIOM() &amp; UIDevice.model
  14. PAT (Advanced Level) 1053. Path of Equal Weight (30)
  15. 今天遇到了一个Spring出现的一个未知错误,分享下
  16. 基础知识全面LINUX
  17. APK Multi-Tool强大的APK反编译工具终极教程
  18. springmvc文件上传和拦截器
  19. Unity StrangeIoC HelloWorld
  20. linux 服务管理

热门文章

  1. JavaBean的学习
  2. JSP中的两种跳转方式分别是什么,有什么区别?
  3. 用代码触发testng实现并发测试
  4. hive 元数据解析
  5. 腾讯云和阿里云部署web 项目tomcat 日志 中文变成问号
  6. 同步FIFO design and IP level verification
  7. 外部服务器使用jedis操作redis数据库
  8. 【Java】SpringBoot 中从application.yml中获取自定义常量
  9. Django+MySQL Dashboard 网页端数据库可视化
  10. 第八届蓝桥杯java b组第九题