DispatcherServlet是Spring MVC的核心内容,理解它的具体服务流程对于中高级应用开发是不可缺少的,下面将通过对源码进行注释来分析下DispatcherServlet的流程处理
-
doService
作为分发请求的方法,doService方法的作用和servlet中的doService作用类似,接收http请求,然后提供对应的服务
/**
* Exposes the DispatcherServlet-specific request attributes and delegates to {@link #doDispatch}
* for the actual dispatching.
*/
@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 IOC容器设置
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()) {
// Restore the original attribute snapshot, in case of an include.
if (attributesSnapshot != null) {
restoreAttributesAfterInclude(request, attributesSnapshot);
}
}
}
}
这个方法中,做了对快照的处理和部分属性的设置,重要的是所跳转到的doDispatch方法
-
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);
//获得匹配的执行器,如果执行器为空,进行错误处理
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}
//找到对应的执行器-->HandlerAdapter
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
//开始处理请求头,即对GET或POST请求进行处理
String method = request.getMethod();
boolean isGet = "GET".equals(method);
//GET处理
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;
}
//执行处理器,返回ModelAndView
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);
}
}
}
}
Dispatch方法的主要流程是:
- 通过请求找到对应的处理链,包括拦截器和控制器
- 通过处理器找到对应的适配器
- 执行拦截器的事前方法,如果返回false,则流程结束
- 通过适配器运行处理器,返回模型和视图
- 对视图和模型进行处理,执行拦截器事后方法
- 进行视图和模型的解析操作
-
getHandler
在Dispatch方法中,用到了处理器和拦截器,这也是Dispatch方法的核心,接下来就是获得处理器的方法getHandler
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//遍历HandlerMapping
for (HandlerMapping hm : this.handlerMappings) {
if (logger.isTraceEnabled()) {
logger.trace(
"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
}
//将获得的HandlerMapping对象进行转换HandlerExecutionChain对象
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
return handler;
}
}
return null;
}
HandlerMapping是SpringMVC启动时初始化的处理器映射,这里做的操作主要是转换成HandlerExecutionChain对象,也就是拦截器链,成员属性如下
public class HandlerExecutionChain {
private static final Log logger = LogFactory.getLog(HandlerExecutionChain.class);
//控制器对象
private final Object handler;
//拦截器数组
private HandlerInterceptor[] interceptors;
//拦截器链表
private List<HandlerInterceptor> interceptorList;
//拦截器下标,在对拦截器进行注册时起定位作用
private int interceptorIndex = -1;
......
}
在这个对象里用到的成员属性都是使用HandlerInterceptor声明的,点进HandlerInterceptor,可以看到有一段对HandlerInterceptor的介绍
* <p>HandlerInterceptor is basically similar to a Servlet Filter, but in
* contrast to the latter it just allows custom pre-processing with the option
* of prohibiting the execution of the handler itself, and custom post-processing.
* Filters are more powerful, for example they allow for exchanging the request
* and response objects that are handed down the chain. Note that a filter
* gets configured in web.xml, a HandlerInterceptor in the application context.
翻译过来就是:HandlerInterceptor基本上类似于Servlet过滤器,但与后者不同的是,它允许自定义预处理和自定义后处理,比过滤器更强大,例如,它们允许在链式处理中传递equest和response请求,过滤器是在web.xml中配置的,而拦截器是在application中定义的
这里的自定义预处理和后处理也就是刚才在Dispatch方法中标注出来的操作
HandlerInterceptor有三个方法
public interface HandlerInterceptor {
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception;
void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception;
void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception;
}
分别对应拦截器处理前,处理时,处理后所用到的方法,这就是处理器handler中拦截器的内容
dispatch方法的流程中最后是对视图进行解析,源码里就是processDispatchResult方法对视图路径进行解析,对视图类型进行判断,比较简单,就不粘出来了
扫码关注我的微信公众号:Java架构师进阶编程 获取最新面试题,电子书
专注分享Java技术干货,包括JVM、SpringBoot、SpringCloud、数据库、架构设计、面试题、电子书等,期待你的关注!