springmvc原始碼 ---DispatcherServlet 處理請求
概述
對於要給servlet 而言,處理請求相關最重要方法是 service(),但是HttpServlet 對service方法進行了封裝,並提供了一些子類重寫的方法 例如 doGet(),doPost(),doPut()…
而 DispatcherServlet 繼承了 HttpServlet 所以只需要重寫HttpServlet暴露出來的方法就好
其實HttpServlet 暴露出來的方法最終呼叫的都是 doGet() 和 doPost()
doGet()和 doPost()
DispatcherServlet 的 doGet()和 doPost()是在 FrameworkServlet
@Override
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);
}
可以看到不論是 doGet() 還是 doPost() 最終呼叫的都是 processRequest(request, response)
直接追溯到核心程式碼
FrameworkServlet.processRequest()>DispatcherServlet .doService()>DispatcherServlet .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 {
//檔案上傳相關,如果傳過來的物件是 MultipartContent
// 那麼就會轉換 request => MultipartHttpServletRequest
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// Determine handler for the current request.
// 根據request 資訊找到對應的Handler
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
// 如果沒有找到對應的Handler ,那麼通過response 反饋錯誤資訊
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
// 獲取介面卡
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
// 處理lastModified
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
// 處理攔截前的邏輯
if (!mappedHandler.applyPreHandle(processedRequest, response)) {//也就說前攔截如果執行失敗了 就會return
return;
}
// Actually invoke the 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) {
// As of 4.3, we're processing Errors thrown from handler methods as well,
// making them available for @ExceptionHandler methods and other scenarios.
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
//處理返回值 渲染檢視 裡面會執行攔截後
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);
}
}
}
}
- 首先處理檔案上傳,如果reques 是MultipartContext 型別的 request 裝換為 MultipartHttpServletRequest
- 根據request 資訊找到對應的 Handler ,並且這裡的Handler 是一個鏈 ,是 處理器+攔截器鏈
- 如果沒有找到對應的Handler ,那麼通過response 反饋錯誤資訊
- 獲取介面卡 處理 GET 和 Head 請求的 lastModified 瀏覽器快取 (用來記錄頁面的最後修改時間。當客戶端訪問頁面時,伺服器會將
頁面最後修改時間通過 Last-Modified 標識由伺服器發往客戶端,客戶端記錄修改時間,再次請求本地存在的cache頁面時) - 處理攔截前的邏輯
- 業務處理 ,根據具體的介面卡執行處理器
- 注入一個預設的檢視名
- 執行攔截中
- 處理返回值 ,渲染檢視 ,執行攔截後
相關文章
- SpringMVC請求處理過程原始碼簡析SpringMVC原始碼
- Spring MVC原始碼(二) ----- DispatcherServlet 請求處理流程 面試必問SpringMVC原始碼Servlet面試
- SpringMVC原始碼分析3:DispatcherServlet的初始化與請求轉發SpringMVC原始碼Servlet
- SpringMVC原始碼分析:POST請求中的檔案處理SpringMVC原始碼
- springmvc處理ajax請求SpringMVC
- SpringMVC DispatcherServlet原始碼解析SpringMVCServlet原始碼
- Spring框架系列(14) - SpringMVC實現原理之DispatcherServlet處理請求的過程框架SpringMVCServlet
- SpringMVC請求流程原始碼分析SpringMVC原始碼
- SpringMVC原始碼解析系列2-DispatcherServletSpringMVC原始碼Servlet
- SpringMVC處理請求頭、響應頭、編碼行為SpringMVC
- SpringMVC原始碼分析2:SpringMVC設計理念與DispatcherServletSpringMVC原始碼Servlet
- 封裝springmvc處理ajax請求結果封裝SpringMVC
- ThinkPHP6 原始碼分析之請求處理PHP原始碼
- zookeeper原始碼 — 五、處理寫請求過程原始碼
- SpringMVC底層——請求引數處理流程描述SpringMVC
- SpringMVC請求對映handler原始碼解讀SpringMVC原始碼
- Kafka原始碼分析(四) - Server端-請求處理框架Kafka原始碼Server框架
- 直播帶貨原始碼,非同步處理中會處理兩次請求原始碼非同步
- Scrapy原始碼閱讀分析_4_請求處理流程原始碼
- 死磕Spring原始碼-MVC處理HTTP分發請求Spring原始碼MVCHTTP
- yai 請求預處理指令碼AI指令碼
- SpringMVC學習筆記6-指定處理請求型別SpringMVC筆記型別
- SpringMVC 解析(二)DispatcherServletSpringMVCServlet
- 請求資料處理
- tomcat原始碼分析(第四篇 tomcat請求處理原理解析--Container原始碼分析)Tomcat原始碼AI
- TiDB 原始碼閱讀系列文章(二十三)Prepare/Execute 請求處理TiDB原始碼
- 一比一還原axios原始碼(二)—— 請求響應處理iOS原始碼
- springMVC DispatcherServlet 初始化SpringMVCServlet
- springMVC DispatcherServlet 工作流程SpringMVCServlet
- 短影片原始碼,實現預處理防止客戶端頻繁請求原始碼客戶端
- 【原始碼分析】- 在SpringBoot中你會使用REST風格處理請求嗎?原始碼Spring BootREST
- Redis(一):服務啟動及基礎請求處理流程原始碼解析Redis原始碼
- DeferredResult——非同步請求處理非同步
- SpringMVC原始碼之Handler註冊、獲取以及請求controller中方法SpringMVC原始碼Controller
- SpringMVC中如何傳送GET請求、POST請求、PUT請求、DELETE請求。SpringMVCdelete
- nginx 如何處理一個請求Nginx
- Go Web如何處理Web請求?GoWeb
- Netty(二):如何處理io請求?Netty