請求在被Servlet處理之前會先被過濾器處理,之後調用Servlet的service方法來對相應的請求進行處理響應。是以我們這裡分析的入口是Servlet的service方法。
我們在用SpringMVC的時候,通常都會在web.xml中進行這樣的配置:
<servlet>
<servlet-name>spring-mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:learn-spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring-mvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
所有的請求(除靜态資源)将由DispatcherServlet處理。

DispatcherServlet繼承了FrameworkServlet,FrameworkServlet繼承了HttpServletBean,HttpServletBean繼承了HttpServlet,HttpServlet繼承了GenericServlet,GenericServlet則實作了我們最頂級的接口Servlet和ServletConfig。
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
if (logger.isDebugEnabled()) {
String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";
logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed +
" processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");
}
// Keep a snapshot of the request attributes in case of an include,
// to be able to restore the original attributes after the include.
Map<String, Object> attributesSnapshot = null;
if (WebUtils.isIncludeRequest(request)) {
attributesSnapshot = new HashMap<String, Object>();
Enumeration<?> attrNames = request.getAttributeNames();
while (attrNames.hasMoreElements()) {
String attrName = (String) attrNames.nextElement();
if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {
attributesSnapshot.put(attrName, request.getAttribute(attrName));
}
}
}
// Make framework objects available to handlers and view objects.
request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());
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(request, response);
}
finally {
if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// Restore the original attribute snapshot, in case of an include.
if (attributesSnapshot != null) {
restoreAttributesAfterInclude(request, attributesSnapshot);
}
}
}
}
從DispatcherServlet的源碼中我們沒有找到service(ServletRequest req, ServletResponse res)這個方法,但是我們在DispatcherServlet的父類HttpServlet中找到了這個方法,我們去HttpServlet中看看這個方法的内容:
HttpServlet#service
将ServletRequest和ServletResponse轉換為HttpServletRequest和HttpServletResponse
因為web開發,用HTTP協定,是以需要HttpServletRequest和HttpServletResponse
接下來就是調用service(HttpServletRequest request, HttpServletResponse response),
HttpServlet和FrameworkServlet中都找到了這個方法,但是HttpServlet是FrameworkServlet的父類,即FrameworkServlet中重寫了service這個方法,是以我們這裡取FrameworkServlet中去看看這個方法的内容:
FrameworkServlet#service
根據請求的方法類型轉換對應的枚舉類
HttpMethod這個定義了這樣的幾種枚舉類型:GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE;而這些也是RFC标準中幾種請求類型。如果請求類型為PATCH或者沒有找到相應的請求類型的話,則直接調用processRequest這個方法。但是這種情況我們很少很少會遇到。
是以這裡會執行super.service這個方法。即調用HttpServlet中的service方法。我們看一下HttpServlet中這個service方法的内容: