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);//1.检查是否文件上传相关请求
multipartRequestParsed = (processedRequest != request);
// Determine handler for the current request.2.根据当前请求,找到处理当前请求的处理器
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) { //3.没找到就抛异常或发送错误页面 404
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
// 4.获取能执行这个类的所有方法的适配器(反射工具 AnnotationMethodHandlerAdapter)
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 (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Actually invoke the handler.
// 5.处理器的方法被调用了,适配器执行目标方法,返回一个 ModelAndView 对象 mv,返回页面自动装配在view属性里
//目标方法执行完成后的返回值作为视图名,设置保存到 ModelAndView 中,无论目标方法怎么写,最终适配器执行完成以后都会将执行后的信息封装成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;
}
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);
}
//6.转发到目标页面,根据方法最终执行完成后封装的ModelAndView,转发到对应页面,而且ModelAndView中的数据可以从请求域中获取
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) 所有请求过来DispatcherServlet收到请求
2) 调用doDispatch( )方法进行处理
(1).getHandler( ): 根据当前请求地址找到能处理这个请求的目标处理器;
(2).getHandlerAdapter( ): 根据当前处理器类获取到能执行这个处理器方法的适配器;
(3).使用刚才获取到的适配器(AnnotationMethodHandlerAdapter)执行目标方法;
(4).目标方法执行后会返回一个ModelAndView对象;
(5).根据ModelAndView的信息转发到具体的页面,并可以在请求域中取出ModelAndView中的模型数据
SpringMVC-请求处理的大致流程分析---doDispatch( )细节
原文:https://www.cnblogs.com/HerrCaoJavaJourney/p/14506472.html