- SpringMVC執行流程時序圖, 此乃不傳之秘。
- SpringMVC執行流程源碼分析/源碼追蹤, 嘔心瀝血之作。
- SpringMVC源碼版本: 5.1.7.RELEASE
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