doDispatch方法执行流程图
网上随便找的张图片,地址:SpringMVC工作流程详解(11大执行流程步骤) – mikechen
在用户发送请求后,服务器执行经过DispatcherServlet,其中主要工作都在DispatcherServlet的doDispatch
中,本文讲解doDispatch中的几个重要的方法
doDispatch中执行的主要的方法
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
....
//1.获取HandlerExcutionChain (内部拥有Handler)
HandlerExecutionChain mappedHandler = getHandler(processedRequest);
....
//2.获取控制器适配器
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
....
//3.执行handler方法 (如控制器),返回ModelAndView
ModelAndView mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
....
//4.执行拦截器postHandler
mappedHandler.applyPostHandle(processedRequest, response, mv);
.....
//5.处理结果
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
获取HandlerExecutionChain
//1.获取HandlerExcutionChain (内部拥有Handler)
HandlerExecutionChain mappedHandler = getHandler(processedRequest);
HandlerExecutionChain
可以看作是一个Handler,内部有一个handler内部变量,这个handler就是具体的处理器。至于为什么是Object类型?是因为DispatchServlet处理多种请求,处理器Handler的种类多类型复杂,使用Object类型可以起到兼容的作用。(后面的HandlerAdpater
是用来适配不同的Handler,这里用到了适配器模式,多种HandlerAdpater
来适配不同的Handler来达到不同的作用。
getHandler()
方法中,通过循环所有的HandlerMappings,执行getHandler方法来与`Handler匹配,匹配成功后,返回Handler
普通的请求方式,handlerMapping
对应的是RequesMappingHandlerMapping
,这里可以看到匹配handlerMapping
之后,此时HandlerExecutionChain
中的handler
的类型是 HandlerMethod
。所以,不同的请求类型有对赢得HandlerMapping
映射,从而返回不同的类型的handler封装成HandlerExecutionChain
至于获取handler的方法 mapping.getHandler(request)
,是HandlerMapping接口的方法,具体实现在于不同的实现类当中,这里就不一一赘述
获取HandlerAdapter
通过HanlderExecutionChain
中的handler,调用getHandlerAdapter
方法获取HandlerAdapter
//2.获取控制器适配器
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
getHandlerAdapter中,通过遍历handlerAdapters,调用HandlerAdpater的support是方法,获取与handler相匹配的HandlerAdapter
普通请求的handlerAdapter对应的是RequestMappingHandlerAdapter
support方法是继承的AbstractHandlerMethodAdapter
实现的,可以看到如果handler类型是HandlerMethod,并且supportsInternal(handler)
方法返回true就匹配适配器。
supportsInternal
方法又是一个接口,实现的地方在RequestMappingHandlerAdapter
中,这里可以看到直接返回的就是true
其他类型的handler这里就不举例子了
执行控制器返回ModelAndView
控制中就是controller实际业务逻辑的地方,可以看到通过调用HandlerAdapter中的handler方法
// Actually invoke the handler.
ModelAndView mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
看看HandlerAdapter的实现类,以RequestMappingHandlerAdapter为例子,继承了AbstractHandlerMethodAdapter再继承HandlerAdapter接口
AbstractHandlerMethodAdapter中实现了handle方法
handleInternal方法又是一个接口,由RequestMappingHandlerAdapter实现
真正的逻辑也是这里面实现的
@Override
protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ModelAndView mav;
checkRequest(request);
// Execute invokeHandlerMethod in synchronized block if required.
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session);
synchronized (mutex) {
mav = invokeHandlerMethod(request, response, handlerMethod);
}
}
else {
// No HttpSession available -> no mutex necessary
mav = invokeHandlerMethod(request, response, handlerMethod);
}
}
else {
// No synchronization on session demanded at all...
mav = invokeHandlerMethod(request, response, handlerMethod);
}
if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
}
else {
prepareResponse(response);
}
}
return mav;
}
可以看到invokeHandlerMethod
方法返回了ModelAndView, 说明具体的逻辑也就在里面
结果处理
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
processDispatchResult
方法是doDispatch中最后执行的一个方法,里面由处理异常、视图渲染、结果回调等功能的实现
/**
* Handle the result of handler selection and handler invocation, which is
* either a ModelAndView or an Exception to be resolved to a ModelAndView.
*/a
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
@Nullable Exception exception) throws Exception {
boolean errorView = false;
//1.异常处理
if (exception != null) {
if (exception instanceof ModelAndViewDefiningException) {
logger.debug("ModelAndViewDefiningException encountered", exception);
mv = ((ModelAndViewDefiningException) exception).getModelAndView();
}
else {
Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
mv = processHandlerException(request, response, handler, exception);
errorView = (mv != null);
}
}
//2.视图渲染
// Did the handler return a view to render?
if (mv != null && !mv.wasCleared()) {
render(mv, request, response);
if (errorView) {
WebUtils.clearErrorRequestAttributes(request);
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("No view rendering, null ModelAndView returned.");
}
}
if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// Concurrent handling started during a forward
return;
}
//3.回调
if (mappedHandler != null) {
// Exception (if any) is already handled..
mappedHandler.triggerAfterCompletion(request, response, null);
}
}