從doGet、doPost方法入手,在父類FrameworkServlet中
protected final void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
@Override
protected final void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
long startTime = System.currentTimeMillis();
Throwable failureCause = null;
LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
LocaleContext localeContext = buildLocaleContext(request);
RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());
//綁定當前線程
initContextHolders(request, localeContext, requestAttributes);
try {
//進一步處理
doService(request, response);
}
catch ...
finally {
//恢復線程到原始狀態
resetContextHolders(request, previousLocaleContext, previousAttributes);
if (requestAttributes != null) {
requestAttributes.requestCompleted();
}
logResult(request, response, failureCause, asyncManager);
//發佈事件通知
publishRequestHandledEvent(request, response, startTime, failureCause);
}
}
doGet、doPost方法都是調用processRequest方法,做了一些準備工作,然後交由doService方法進一步處理
DispatcherServlet重寫了doService方法
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
...
Map<String, Object> attributesSnapshot = null;
if (WebUtils.isIncludeRequest(request)) {
attributesSnapshot = new HashMap<>();
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));
}
}
}
// 設置變量
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());
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(request, response);
}
finally {
if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// Restore the original attribute snapshot, in case of an include.
if (attributesSnapshot != null) {
restoreAttributesAfterInclude(request, attributesSnapshot);
}
}
}
}
做好準備工作將已經初始化的功能輔助工具變量,如localeResolver、themeResolver等設置到request屬性中。doDispatch才真正進行處理請求。
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
//檢測是否是文件上傳
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
//【標記1】 從handlerMappings獲取相應的handler
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
//【標記2】 從handlerAdapters獲取相應的handlerAdapter
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// 是否支持last-modified
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;
}
// 真正調用handler進行請求的處理
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
//如果沒返回視圖,則使用默認的視圖
applyDefaultViewName(processedRequest, mv);
//調用攔截器的後置方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
//【標記3】處理handler返回的結果
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
【標記1】獲取handler
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
for (HandlerMapping mapping : this.handlerMappings) {
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
getHandler方法主要是從handlerMappings獲取相應的handler,然後封裝成HandlerExecutionChain返回。
【標記2】 獲取HandlerAdapter
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
for (HandlerAdapter adapter : this.handlerAdapters) {
if (adapter.supports(handler)) {
return adapter;
}
}
}
throw...
}
getHandlerAdapter方法主要是從handlerAdapters獲取相應的adapter返回。
【標記3】 視圖渲染
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);
View view;
String viewName = mv.getViewName();
if (viewName != null) {
// 【標記4】通過視圖名獲取View.
view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
if (view == null) {
throw...
}
}
else {
// 檢驗是否存在視圖
view = mv.getView();
if (view == null) {
throw...
}
}
try {
if (mv.getStatus() != null) {
response.setStatus(mv.getStatus().value());
}
//【標記5】
view.render(mv.getModelInternal(), request, response);
}
catch...
}
protected View resolveViewName(String viewName, @Nullable Map<String, Object> model,
Locale locale, HttpServletRequest request) throws Exception {
if (this.viewResolvers != null) {
for (ViewResolver viewResolver : this.viewResolvers) {
View view = viewResolver.resolveViewName(viewName, locale);
if (view != null) {
return view;
}
}
}
return null;
}
【標記4】獲取View對象,以InternalResourceViewResolver爲例,resolveViewName在其父類AbstractCachingViewResolver中
public View resolveViewName(String viewName, Locale locale) throws Exception {
if (!isCache()) {//沒緩存就創建
return createView(viewName, locale);
}
else {
Object cacheKey = getCacheKey(viewName, locale);
View view = this.viewAccessCache.get(cacheKey);
if (view == null) {
synchronized (this.viewCreationCache) {
view = this.viewCreationCache.get(cacheKey);
if (view == null) {
// 子類進行創建
view = createView(viewName, locale);
if (view == null && this.cacheUnresolved) {
view = UNRESOLVED_VIEW;
}
if (view != null) {
this.viewAccessCache.put(cacheKey, view);
this.viewCreationCache.put(cacheKey, view);
}
}
}
}
return (view != UNRESOLVED_VIEW ? view : null);
}
}
UrlBasedViewResolver類
protected View createView(String viewName, Locale locale) throws Exception {
// 檢查是否支持該視圖
if (!canHandle(viewName, locale)) {
return null;
}
// 重定向處理
if (viewName.startsWith(REDIRECT_URL_PREFIX)) {
String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length());
RedirectView view = new RedirectView(redirectUrl,
isRedirectContextRelative(), isRedirectHttp10Compatible());
String[] hosts = getRedirectHosts();
if (hosts != null) {
view.setHosts(hosts);
}
return applyLifecycleMethods(REDIRECT_URL_PREFIX, view);
}
// 轉發處理
if (viewName.startsWith(FORWARD_URL_PREFIX)) {
String forwardUrl = viewName.substring(FORWARD_URL_PREFIX.length());
InternalResourceView view = new InternalResourceView(forwardUrl);
return applyLifecycleMethods(FORWARD_URL_PREFIX, view);
}
// 回到父類的createView進行調用loadView
return super.createView(viewName, locale);
}
protected View createView(String viewName, Locale locale) throws Exception {
return loadView(viewName, locale);
}
protected abstract View loadView(String viewName, Locale locale) throws Exception;
protected View loadView(String viewName, Locale locale) throws Exception {
//真正創建View
AbstractUrlBasedView view = buildView(viewName);
//交由spring管理聲明週期
View result = applyLifecycleMethods(viewName, view);
return (view.checkResource(locale) ? result : null);
}
真正創建View在buildView方法
protected AbstractUrlBasedView buildView(String viewName) throws Exception {
Class<?> viewClass = getViewClass();
//創建
AbstractUrlBasedView view = (AbstractUrlBasedView) BeanUtils.instantiateClass(viewClass);
//設置前綴、後綴
view.setUrl(getPrefix() + viewName + getSuffix());
//類型設置
String contentType = getContentType();
if (contentType != null) {
view.setContentType(contentType);
}
...
return view;
}
【標記5】頁面跳轉
AbstractView類
public void render(@Nullable Map<String, ?> model, HttpServletRequest request,
HttpServletResponse response) throws Exception {
...
//獲取整合一些屬性
Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);
prepareResponse(request, response);
//處理頁面跳轉
renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
}
InternalResourceView類
protected void renderMergedOutputModel(
Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
// 把屬性設置到request中
exposeModelAsRequestAttributes(model, request);
// Expose helpers as request attributes, if any.
exposeHelpers(request);
// 獲取路徑
String dispatcherPath = prepareForRendering(request, response);
//拿到請求派發器
RequestDispatcher rd = getRequestDispatcher(request, dispatcherPath);
if (rd == null) {
throw...
}
if (useInclude(request, response)) {
response.setContentType(getContentType());
rd.include(request, response);
}
else {
...
rd.forward(request, response);
}
}
總結參考:SpringMVC請求流程詳解