DispatcherServlet 是什么
DispatcherServlet 是spring mvc中最最核心的类了,我们可以理解为DispatcherServlet是spring mvc 中大脑,它负责调度工作
从图中可以看出DispatcherServlet得继承关系大致如下
DispatcherServlet-->FrameworkServlet-->HttpServletBean-->HttpServlet-->GenericServlet
从继承关系可以得知DispatcherServlet本质上还是一个servlet, servlet得生命周期分为三个阶段
- init()初始化阶段
- service()处理请求阶段
- destroy()销毁阶段
接下来我们从每个阶段来解析DispatcherServlet
DispatcherServlet初始化
DispatcherServlet在初始化得时候对spring mvc 九大组件进行了初始化功能
//初始化方法
@Override
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}
/**
* Initialize the strategy objects that this servlet uses.
* <p>May be overridden in subclasses in order to initialize further strategy objects.
*/
//分别调用了spring mvc中九大组件得初始化方法
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
}
这个时候有的小伙伴就会疑惑,初始化方法不是init()吗,怎么会是onRefresh()方法,其实通过一层层得类继承初始化方法早已不是init(),有兴趣得可以看一下
spring mvc 之 FrameworkServlet 源码解析
HttpServletBean 源码解析
这里只大概梳理一下
- HttpServletBean 覆盖 GenericServlet 的 init() 方法,该方法调用 initServletBean() 方法,该方法被 FrameworkServlet 覆盖
- 在 FrameworkServlet 的 initServletBean() 方法中,它调用 initWebApplicationContext() 方法
- 在该方法中,它检查 webApplicationContext 是否是 ConfigurableWebApplicationContext 的实例
- 如果是,则调用 configureAndRefreshWebApplicationContext() 方法
- 因为它在 webApplicationContext 上调用 refresh 方法
- 查看 AbstractApplicationContext 中 refresh() 方法的实现,最后调用了 finishRefresh() 方法
- 在该方法中它发布 ContextRefreshedEvent
- 在 FrameworkServlet 中有实现 ApplicationListener 的私有类 ContextRefreshListener
- 此类上的 onApplicationEvent() 方法调用 FrameworkServlet 的 onApplicationEvent() 方法
- 在该方法中,它调用由 DispatcherServlet 覆盖的 onRefresh 方法
DispatcherServlet处理请求
doService是DispatcherServlet处理请求得入口方法,主要流程如下
- 是否include请求,是得话则进行快照备份,后面在finally会对include中得属性还原
- 设置一些常见得属性到request中,例如应用上下文,国际化解析器,主题解析器
- 判断flashMap是否存在,存在得话则进行复原
- 将请求路径对象化(后面映射匹配的时候用的到)
- 调用doDispatch处理请求
- 复原include请求中得属性,还原RequestPath
@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.
// 是否include请求,是得话则进行快照备份,后面在finally会对include中得属性还原
Map<String, Object> 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中,例如应用上下文,国际化解析器,主题解析器
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是否存在,存在得话则进行复原
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);
}
//调用doDispatch是真正处理请求得地方
try {
doDispatch(request, response);
}
//复原include请求中得属性
finally {
if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// Restore the original attribute snapshot, in case of an include.
if (attributesSnapshot != null) {
restoreAttributesAfterInclude(request, attributesSnapshot);
}
}
//还原RequestPath
if (this.parseRequestPath) {
ServletRequestPathUtils.setParsedRequestPath(previousRequestPath, request);
}
}
}
- 验证当前是否是文件上传请求,是的话重新包装请求
- 获取Handler处理器,没有获取到则抛出404异常
- 获取HandlerAdapter处理适配器
- 判断当请是否是HEAD和GET,判断是否有浏览器缓存,有的话直接返回
- 执行拦截器得PreHandle方法,如果拦截器返回false直接 return;
- 执行处理器处理请求,返回ModelAndView对象
- 当前请求是否异步处理,是的话直接return;
- 执行拦截器的PostHandle方法
- 异常处理,渲染页面,执行拦截器的afterCompletion()方法
- finally块,异步处理调用对应的拦截器,是文件上传请求则删除上传中生成的临时文件
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.
//获取Handler处理器,没有获取到则抛出404异常
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
//获取HandlerAdapter处理适配器
HandlerAdapter ha = getHandlerAdapter处理适配器(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = HttpMethod.GET.matches(method);
//HEAD和GET方法,判断是否有浏览器缓存,有的话直接返回
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;
}
// Actually invoke the handler.
//执行处理器处理请求,返回ModelAndView对象
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
//当前请求是否异步处理
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
//检查当前ModelAndView对象是否没有视图名,没有得话则给一个默认的视图名
applyDefaultViewName(processedRequest, mv);
//执行拦截器的PostHandle方法
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);
}
//异常处理,渲染页面,执行拦截器的afterCompletion()方法
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 {
//处理文件上传中的一些临时文件
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
DispatcherServlet得流程大致就如上,销毁阶段这个没有什么东西要说的,其中有很多分支处理是非常重要得,比如ha.handle(processedRequest, response, mappedHandler.getHandler());还有如何获取HandlerMappings,如何获取HandlerAdapter等流程,后面会慢慢去解析