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頁面時) - 處理攔截前的邏輯
- 業務處理 ,根據具體的介面卡執行處理器
- 注入一個預設的檢視名
- 執行攔截中
- 處理返回值 ,渲染檢視 ,執行攔截後
相關文章
- Spring MVC原始碼(二) ----- DispatcherServlet 請求處理流程 面試必問SpringMVC原始碼Servlet面試
- SpringMVC請求處理過程原始碼簡析SpringMVC原始碼
- SpringMVC原始碼剖析(四)- DispatcherServlet請求轉發的實現SpringMVC原始碼Servlet
- SpringMVC原始碼分析3:DispatcherServlet的初始化與請求轉發SpringMVC原始碼Servlet
- SpringMVC原始碼分析:POST請求中的檔案處理SpringMVC原始碼
- SpringMVC請求處理流程SpringMVC
- SpringMVC DispatcherServlet原始碼解析SpringMVCServlet原始碼
- SpringMVC系列原始碼:DispatcherServletSpringMVC原始碼Servlet
- Spring框架系列(14) - SpringMVC實現原理之DispatcherServlet處理請求的過程框架SpringMVCServlet
- SpringMVC請求流程原始碼分析SpringMVC原始碼
- SpringMVC原始碼解析系列2-DispatcherServletSpringMVC原始碼Servlet
- zookeeper原始碼 — 五、處理寫請求過程原始碼
- ThinkPHP6 原始碼分析之請求處理PHP原始碼
- 【Zookeeper】原始碼分析之請求處理鏈(一)原始碼
- 封裝springmvc處理ajax請求結果封裝SpringMVC
- SpringMVC原始碼分析2:SpringMVC設計理念與DispatcherServletSpringMVC原始碼Servlet
- SpringMVC原始碼剖析(二)- DispatcherServlet的前世今生SpringMVC原始碼Servlet
- SpringMVC底層——請求引數處理流程描述SpringMVC
- 直播帶貨原始碼,非同步處理中會處理兩次請求原始碼非同步
- SpringMVC請求對映handler原始碼解讀SpringMVC原始碼
- Scrapy原始碼閱讀分析_4_請求處理流程原始碼
- 【Zookeeper】原始碼分析之請求處理鏈(三)之SyncRequestProcessor原始碼
- 【Zookeeper】原始碼分析之請求處理鏈(二)之PrepRequestProcessor原始碼
- yai 請求預處理指令碼AI指令碼
- SpringMVC原始碼剖析(三)- DispatcherServlet的初始化流SpringMVC原始碼Servlet
- SpringMVC原始碼剖析(三)- DispatcherServlet的初始化流程SpringMVC原始碼Servlet
- 死磕Spring原始碼-MVC處理HTTP分發請求Spring原始碼MVCHTTP
- 【Zookeeper】原始碼分析之請求處理鏈(四)之FinalRequestProcessor原始碼
- 【spring原始碼學習】springMVC之對映,攔截器解析,請求資料注入解析,DispatcherServlet執行過程原始碼SpringMVCServlet
- springMVC原始碼學習之:springMVC響應請求的幾種方法SpringMVC原始碼
- Picasso原始碼分析(六):BitmapHunter與請求結果的處理原始碼
- SpringMVC學習筆記6-指定處理請求型別SpringMVC筆記型別
- 請求資料處理
- wordpress 處理 ajax 請求
- Mongodb請求處理流程MongoDB
- .NET處理HTTP請求HTTP
- 處理REST SOE請求REST
- 請求處理管道個人理解