# Spring MVC中源码分析-DispatcherServlet
[TOC]
## DispatcherServlet的继承结构
前面说了DispatcerServlet是SpringMVC最重要类之一了,其实DispatcherServlet也是一个Servlet,所以这里首先看看DispatcherServlet的继承结构

从上图可以看到,doGet/doPost是交由父类FrameworkServlet来进行处理的,然后再调用最终的doDispatch方法
## doDispatch方法解析
```java
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 {
// 1 检查是否是⽂件上传的请求
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// Determine handler for the current request.
/*
2 取得处理当前请求的Controller,这⾥也称为Handler,即处理器
这⾥并不是直接返回 Controller,⽽是返回 HandlerExecutionChain 请求处
理链对象
该对象封装了Handler和Inteceptor
*/
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
// 如果 handler 为空,则返回404
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
// 3 获取处理请求的处理器适配器 HandlerAdapter
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
// 处理 last-modified 请求头
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request,
mappedHandler.getHandler());
if (new ServletWebRequest(request,
response).checkNotModified(lastModified) && isGet) {
return;
}
}
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Actually invoke the handler.
// 4 实际处理器处理请求,返回结果视图对象
mv = ha.handle(processedRequest, response,
mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
// 结果视图对象的处理
applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
} catch (Exception ex) {
dispatchException = ex;
} catch (Throwable err) {
// As of 4.3, we're processing Errors thrown from handler methods
as well,
// making them available for @ExceptionHandler methods and other
scenarios.
dispatchException = new NestedServletException("Handler dispatch
failed", err);
}
// 5 跳转⻚⾯,渲染视图
processDispatchResult(processedRequest, response, mappedHandler, mv,
dispatchException);
} catch (Exception ex) {
//最终会调⽤HandlerInterceptor的afterCompletion ⽅法
triggerAfterCompletion(processedRequest, response, mappedHandler,
ex);
} catch (Throwable err) {
//最终会调⽤HandlerInterceptor的afterCompletion ⽅法
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步-判断是否是上传文件请求
```java
protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {
//配置上传文件解析器并且请求类型是multipart/开头的,则为上传文件
if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) {
}
}
@Override
public boolean isMultipart(HttpServletRequest request) {
return StringUtils.startsWithIgnoreCase(request.getContentType(), "multipart/");
}
```
## 第2步-获取具体的HandlerExecutionChain
取得处理当前请求的Controller,这⾥也称为Handler,即处理器,这⾥并不是直接返回 Controller,⽽是返回 HandlerExecutionChain 请求处理链对象,该对象封装了Handler和Inteceptor

getHandler这里我们用注解写的,这里就是使用`RequestMappingHandlerMapping`进行解析的,通过URL连接前往初始化时根据注解中url缓存起来的handlerMethod

```java
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
Object handler = getHandlerInternal(request);
//..
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
//..
return executionChain;
}
```
这里通过 getHandlerExecutionChain方法获取HandlerExecutionChain的处理链,这里主要是将所有符合的拦截器加入到对应的拦截链中
```java
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
if (interceptor instanceof MappedInterceptor) {
MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
//判断拦截器是否符合对应请求,是的话,加入到拦截链中
if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
}
else {
chain.addInterceptor(interceptor);
}
}
return chain;
}
```
## 第3步-获取处理请求的处理器适配器 HandlerAdapter
这里是使用适配器模式找到相匹配的适配器

这里三种适配器是针对我们使用不同的方法创建的Controller来匹配的,原理都是一样的,使用适配器模式,找到匹配的适配器,通过适配器再调用具体的方法
三个适配器都实现了HandlerAdapter接口,这里看一下`HandlerAdapter`
```java
public interface HandlerAdapter {
/**
* Given a handler instance, return whether or not this {@code HandlerAdapter}
* can support it. Typical HandlerAdapters will base the decision on the handler
* type. HandlerAdapters will usually only support one handler type each.
* <p>A typical implementation:
* <p>{@code
* return (handler instanceof MyHandler);
* }
* @param handler handler object to check
* @return whether or not this object can use the given handler
*/
boolean supports(Object handler);
/**
* Use the given handler to handle this request.
* The workflow that is required may vary widely.
* @param request current HTTP request
* @param response current HTTP response
* @param handler handler to use. This object must have previously been passed
* to the {@code supports} method of this interface, which must have
* returned {@code true}.
* @throws Exception in case of errors
* @return a ModelAndView object with the name of the view and the required
* model data, or {@code null} if the request has been handled directly
*/
@Nullable
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
/**
* Same contract as for HttpServlet's {@code getLastModified} method.
* Can simply return -1 if there's no support in the handler class.
* @param request current HTTP request
* @param handler handler to use
* @return the lastModified value for the given handler
* @see javax.servlet.http.HttpServlet#getLastModified
* @see org.springframework.web.servlet.mvc.LastModified#getLastModified
*/
long getLastModified(HttpServletRequest request, Object handler);
}
```
使用`supports`方法判断是否是符合的适配器,使用handle调用最终的需要调用的方法
## 第4步实际处理器处理请求,返回结果视图对象
使用上面获得到的HandlerAdapter反射进行调用具体的handler方法,获得最终返回的视图对象,





## 第5步 processDispatchResult方法跳转⻚⾯,渲染视图
- render⽅法完成渲染

- 视图解析器解析出View视图对象

- 在解析出View视图对象的过程中会判断是否重定向、是否转发等,不同的情况封装的是不同的View实现

- 解析出View视图对象的过程中,要将逻辑视图名解析为物理视图名

- 封装View视图对象之后,调⽤了view对象的render⽅法

- 渲染数据

- 把modelMap中的数据暴露到request域中,这也是为什么后台model.add之后在jsp中可以从请求
域取出来的根本原因

- 将数据设置到请求域中

Spring MVC学习笔记(三) -SpringMVC源码分析之DispatcherServlet