Spring MVC請求處理具體流程
阿新 • • 發佈:2019-02-10
// 前端控制器分派方法
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
int interceptorIndex = -1;
try {
ModelAndView mv;
boolean errorView = false;
try {
// 檢查是否是請求是否是multipart(如檔案上傳),如果是將通過MultipartResolver解析
processedRequest = checkMultipart(request);
// 步驟2、請求到處理器(頁面控制器)的對映,通過HandlerMapping進行對映
mappedHandler = getHandler(processedRequest, false);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}
// 步驟3、處理器適配,即將我們的處理器包裝成相應的介面卡(從而支援多種型別的處理器)
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// 304 Not Modified快取支援
// 此處省略具體程式碼
// 執行處理器相關的攔截器的預處理(HandlerInterceptor.preHandle)
// 此處省略具體程式碼
// 步驟4、由介面卡執行處理器(呼叫處理器相應功能處理方法)
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
// Do we need view name translation?
if (mv != null && !mv.hasView()) {
mv.setViewName(getDefaultViewName(request));
}
// 執行處理器相關的攔截器的後處理(HandlerInterceptor.postHandle)
// 此處省略具體程式碼
}
catch (ModelAndViewDefiningException ex) {
logger.debug("ModelAndViewDefiningException encountered", ex);
mv = ex.getModelAndView();
}
catch (Exception ex) {
Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
mv = processHandlerException(processedRequest, response, handler, ex);
errorView = (mv != null);
}
// 步驟5 步驟6、解析檢視並進行檢視的渲染
// 步驟5 由ViewResolver解析View(viewResolver.resolveViewName(viewName, locale))
// 步驟6 檢視在渲染時會把Model傳入(view.render(mv.getModelInternal(), request, response);)
if (mv != null && !mv.wasCleared()) {
render(mv, processedRequest, response);
if (errorView) {
WebUtils.clearErrorRequestAttributes(request);
}
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +
"': assuming HandlerAdapter completed request handling");
}
}
// 執行處理器相關的攔截器的完成後處理(HandlerInterceptor.afterCompletion)
// 此處省略具體程式碼
catch (Exception ex) {
// Trigger after-completion for thrown exception.
triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
throw ex;
}
catch (Error err) {
ServletException ex = new NestedServletException("Handler processing failed", err);
// Trigger after-completion for thrown exception.
triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
throw ex;
}
finally {
// Clean up any resources used by a multipart request.
if (processedRequest != request) {
cleanupMultipart(processedRequest);
}
}
}
核心架構的具體流程步驟如下:
1、 首先使用者傳送請求——>DispatcherServlet,前端控制器收到請求後自己不進行處理,而是委託給其他的解析器進行處理,作為統一訪問點,進行全域性的流程控制;
2、 DispatcherServlet——>HandlerMapping, HandlerMapping將會把請求對映為HandlerExecutionChain物件(包含一個Handler處理器(頁面控制器)物件、多個HandlerInterceptor攔截器)物件,通過這種策略模式,很容易新增新的對映策略;
3、 DispatcherServlet——>HandlerAdapter,HandlerAdapter將會把處理器包裝為介面卡,從而支援多種型別的處理器,即介面卡設計模式的應用,從而很容易支援很多型別的處理器;
4、 HandlerAdapter——>處理器功能處理方法的呼叫,HandlerAdapter將會根據適配的結果呼叫真正的處理器的功能處理方法,完成功能處理;並返回一個ModelAndView物件(包含模型資料、邏輯檢視名);
5、 ModelAndView的邏輯檢視名——> ViewResolver, ViewResolver將把邏輯檢視名解析為具體的View,通過這種策略模式,很容易更換其他檢視技術;
6、 View——>渲染,View會根據傳進來的Model模型資料進行渲染,此處的Model實際是一個Map資料結構,因此很容易支援其他檢視技術;
7、 返回控制權給DispatcherServlet,由DispatcherServlet返回響應給使用者,到此一個流程結束。