天天看點

SpringMVC的執行流程源碼分析?聯系方式

- SpringMVC執行流程時序圖, 此乃不傳之秘。

SpringMVC的執行流程源碼分析?聯系方式

- SpringMVC執行流程源碼分析/源碼追蹤, 嘔心瀝血之作。

  • SpringMVC源碼版本: 5.1.7.RELEASE
SpringMVC的執行流程源碼分析?聯系方式

1. 源碼分析: Servlet

public interface Servlet {
    // 初始化方法,構造方法後執行
    void init(ServletConfig var1);
    // 每次通路servlet時候執行
    void service(ServletRequest var1, ServletResponse var2);
    // 停止伺服器時候執行
    void destroy();
}
           

2. 源碼追蹤: FrameworkServlet

protected void service(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
    HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
    if (httpMethod != HttpMethod.PATCH && httpMethod != null) {
        super.service(request, response);
    } else {
        // 最終都會執行處理請求的方法
        this.processRequest(request, response);
    }
}
           

3. 源碼追蹤: DispatcherServlet

protected void doService(HttpServletRequest request, HttpServletResponse
response) throws Exception {
this.logRequest(request);
Map<String, Object> attributesSnapshot = null;
if (WebUtils.isIncludeRequest(request)) {
attributesSnapshot = new HashMap();
Enumeration attrNames = request.getAttributeNames();
label95:
while(true) {
String attrName;
do {
if (!attrNames.hasMoreElements()) {
break label95;
}
attrName = (String)attrNames.nextElement();
} while(!this.cleanupAfterInclude &&
!attrName.startsWith("org.springframework.web.servlet"));
attributesSnapshot.put(attrName,
request.getAttribute(attrName));
}
}
request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE,
this.getWebApplicationContext());
request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
request.setAttribute(THEME_SOURCE_ATTRIBUTE, this.getThemeSource());
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);
}
try {
// 最終都會執行doDispatch方法
this.doDispatch(request, response);
} finally {
if
(!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted() &&
attributesSnapshot != null) {
this.restoreAttributesAfterInclude(request,
attributesSnapshot);
}
}
}
           
protected void doDispatch(HttpServletRequest request, HttpServletResponse
response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
try {
ModelAndView mv = null;
Object dispatchException = null;
try {
processedRequest = this.checkMultipart(request);
multipartRequestParsed = processedRequest != request;
// 根據URI擷取到具體的處理器方法 (三大元件之一: 處理器映射器)
mappedHandler = this.getHandler(processedRequest);
if (mappedHandler == null) {
this.noHandlerFound(processedRequest, response);
return;
}
// 擷取到處理器擴充卡 (三大元件之一: 處理器擴充卡)
HandlerAdapter ha =
this.getHandlerAdapter(mappedHandler.getHandler());
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;
}
// 擴充卡通過反射調用處理器方法
// 并傳回視圖和模型
mv = ha.handle(processedRequest, response,
mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
// 如果視圖是空采用預設視圖
this.applyDefaultViewName(processedRequest, mv);
// 攔截器處理
mappedHandler.applyPostHandle(processedRequest, response,
mv);
} catch (Exception var20) {
dispatchException = var20;
} catch (Throwable var21) {
dispatchException = new NestedServletException("Handler
dispatch failed", var21);
}
// 調用視圖解析器處理結果 (三大元件之一: 視圖解析器)
this.processDispatchResult(processedRequest, response,
mappedHandler, mv, (Exception)dispatchException);
} catch (Exception var22) {
this.triggerAfterCompletion(processedRequest, response,
mappedHandler, var22);
} catch (Throwable var23) {
this.triggerAfterCompletion(processedRequest, response,
mappedHandler, new NestedServletException("Handler processing failed",
var23));
}
} finally {
if (asyncManager.isConcurrentHandlingStarted()) {
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest,
response);
}
} else if (multipartRequestParsed) {
this.cleanupMultipart(processedRequest);
}
}
}
           

4. 追蹤源碼: DispatcherServlet

protected void render(ModelAndView mv, HttpServletRequest request,
HttpServletResponse response) throws Exception {
Locale locale = this.localeResolver != null ?
this.localeResolver.resolveLocale(request) : request.getLocale();
response.setLocale(locale);
String viewName = mv.getViewName();
View view;
if (viewName != null) {
// 根據視圖解析器建立視圖對象
view = this.resolveViewName(viewName, mv.getModelInternal(),
locale, request);
if (view == null) {
throw new ServletException("Could not resolve view with name '"
+ mv.getViewName() + "' in servlet with name '" + this.getServletName() +
"'");
}
} else {
view = mv.getView();
if (view == null) {
throw new ServletException("ModelAndView [" + mv + "] neither
contains a view name nor a View object in servlet with name '" +
this.getServletName() + "'");
}
}
if (this.logger.isTraceEnabled()) {
this.logger.trace("Rendering view [" + view + "] ");
}
try {
if (mv.getStatus() != null) {
response.setStatus(mv.getStatus().value());
}
// 視圖渲染: AbstractView
view.render(mv.getModelInternal(), request, response);
} catch (Exception var8) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Error rendering view [" + view + "]", var8);
}
throw var8;
}
}
           

5. 追蹤源碼: AbstractView

public void render(@Nullable Map<String, ?> model, HttpServletRequest
request, HttpServletResponse response) throws Exception {
if (this.logger.isDebugEnabled()) {
this.logger.debug("View " + this.formatViewName() + ", model " +
(model != null ? model : Collections.emptyMap()) +
(this.staticAttributes.isEmpty() ? "" : ", static attributes " +
this.staticAttributes));
}
Map<String, Object> mergedModel = this.createMergedOutputModel(model,
request, response);
this.prepareResponse(request, response);
// 合并視圖與資料模型: InternalResourceView
this.renderMergedOutputModel(mergedModel,
this.getRequestToExpose(request), response);
}
           

6. 追蹤源碼: InternalResourceView

protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
        this.exposeModelAsRequestAttributes(model, request);
        this.exposeHelpers(request);
        String dispatcherPath = this.prepareForRendering(request, response);
        RequestDispatcher rd = this.getRequestDispatcher(request, dispatcherPath);
        if (rd == null) {
            throw new ServletException("Could not get RequestDispatcher for [" + this.getUrl() + "]: Check that the corresponding file exists within your web application archive!");
        } else {
            if (this.useInclude(request, response)) {
                response.setContentType(this.getContentType());
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Including [" + this.getUrl() + "]");
                }

                rd.include(request, response);
            } else {
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Forwarding to [" + this.getUrl() + "]");
                }
                // 轉發頁面
                rd.forward(request, response);
            }

        }
    }
           

7. 追蹤源碼: RedirectView

protected void renderMergedOutputModel(Map<String, Object> model,
HttpServletRequest request, HttpServletResponse response) throws IOException
{
    String targetUrl = this.createTargetUrl(model, request);
    targetUrl = this.updateTargetUrl(targetUrl, model, request, response);
    RequestContextUtils.saveOutputFlashMap(targetUrl, request, response);
    // 重定向位址
    this.sendRedirect(request, response, targetUrl, this.http10Compatible);
}
           

聯系方式

  • QQ 569284276
  • EM [email protected]
  • WX 569284276
  • 點選連結加入群聊【8080實驗室】: 537950751

繼續閱讀