Spring?MVC DispatcherServlet處理請求過程示例詳解
引言
前面講過了DispatcherServlet的初始化過程(源碼角度的DispatcherServlet的具體初始化過程還沒說,先放一放),今天說一下DispatcherServlet處理請求的過程。
處理過程
- WebApplicationContext綁定在當前request屬性上(屬性鍵值DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE)
- localResolver綁定在request的屬性上(屬性鍵值LOCALE_RESOLVER_ATTRIBUTE)
- themeResolver綁定在request屬性上(屬性鍵值HEME_RESOLVER_ATTRIBUTE)
- servlet容器配置了multipart resolver,并且當前請求包含multpart file,則包裝當前request為MultipartHttpServletRequest。
- 匹配當前請求的handlerMappings,獲取到HandlerExecutionChain,匹配getHandlerAdapter
- 調(diào)用HandlerExecutionChain的applyPreHandle方法:獲取攔截器,調(diào)用攔截器的preHandle方法
- 調(diào)用HandlerAdapter的handle方法,這兒會匹配并執(zhí)行Conroller方法
- 執(zhí)行HandlerExecutionChain的applyPostHandle方法:調(diào)用攔截器的postHandle方法
- 執(zhí)行processDispatchResult方法,其中會調(diào)用攔截器的afterCompletion方法
以上過程都被try catch包圍起來了,所以才會有Spring MVC的異常處理機制:應用層不管哪里(controller、service、dao層...)拋出的異常,都會在這里被捕獲到,注冊到WebApplicationContext容器中的HandlerExceptionResolver beans就有機會統(tǒng)一處理異常。
可以通過DispatcherServlet的初始化參數(shù)來定制化其行為,參數(shù)可以通過web.xml指定,包括:
- contextClass:指定當前DispatcherServlet綁定的容器類(ConfigurableWebApplicationContext的實現(xiàn)類),默認為XmlWebApplicationContext 。
- contextConfigLocation:上述contextClass指定的容器類的配置文件的位置,可以指定多個配置文件,逗號分割。
- namespace:WebApplicationContext的namespace,默認[servlet-name]-servlet。
- throwExceptionIfNoHandlerFound:某一請求request沒有匹配到handle的話,是否拋出NoHandlerFoundException異常,NoHandlerFoundException隨后可以被HandlerExceptionResolver捕獲并處理。默認情況下該參數(shù)設置為false,DispatherServlet不拋出異常、直接導航到404。注意:如果配置了默認Servlet Handler(default servlet handling)的話,那么沒匹配到的request會導航到默認handler處理,永遠不會出現(xiàn)404。
攔截
HandlerMapping支持攔截器,攔截器需實現(xiàn)SpringMVC的HandlerInterceptor接口(org.springframework.web.servlet),包含如下方法:
- preHandle:HandlerMapping處理請求之前發(fā)生。
- postHandle:HandlerMapping處理請求之后發(fā)生。
- afterCompletion:整個請求處理完成之后。
preHandle返回true則請求繼續(xù)被處理,返回false則后續(xù)不會再處理請求。
postHandle對@ResponseBody和ResponseEntity方法幾乎沒有什么作用,因為response已經(jīng)在postHandle之前被HandlerAdapter處理完成了,因此不可能被postHandle修改了。比如你想通過postHandle在response header中增加一個頭信息是不可能的了。這種需求只能通過ResponseBodyAdvice、 Controller Advice 或者直接在RequestMappingHandlerAdapter中直接實現(xiàn)。
異常處理
HandleMapping、HandlerAdapter、Controller中發(fā)生的任何異常,都可以被DispatcherServlet捕獲、交給HandlerExceptionResolver bean去處理異常。
SpringMVC提供如下異常處理的實現(xiàn)類:
異常處理鏈我們可以配置多個HandlerExceptionResolver作為異常處理鏈(exception resolver chain)來處理異常,可以通過order屬性指定其處理順序,order值越大、在chain中排名越靠后。
HandlerExceptionResolver可以返回:
- ModelAndView :錯誤頁面。
- 空ModelAndView:錯誤已經(jīng)被處理,不需要導航到錯誤頁面。
- Null:當前Resolver不處理,異常繼續(xù)向上拋給chain中后面的Resolver,直到最后如果沒有Resolver處理該異常的話,異常會拋出給Servlet容器(比如給到Tomcat,這種情況下Tomcat也不處理,可能就會直接拋出給前臺)。
SpringMVC會自動配置內(nèi)建的異常處理器,我們可以通過配置客戶化異常處理器。SpringMVC的異常處理相對比較重要,后面我們還會從源碼和應用角度做一次分析。
容器錯誤頁面
如果異常沒有被任何HandlerExceptionResolver處理,而且,如果response status被設置為4xx、5xx的話,servlet容器(比如tomcat)會導航到默認的錯誤處理頁面,假如容器配置了錯誤處理頁面的話??梢酝ㄟ^web.xml配置:
<error-page> <location>/error</location> </error-page>
以上配置需要DispatcherServlet進一步處理:
@RestController public class ErrorController { @RequestMapping(path = "/error") public Map<String, Object> handle(HttpServletRequest request) { Map<String, Object> map = new HashMap<>(); map.put("status", request.getAttribute("jakarta.servlet.error.status_code")); map.put("reason", request.getAttribute("jakarta.servlet.error.message")); return map; } }
以上就是Spring MVC 六 - DispatcherServlet處理請求過程的詳細內(nèi)容,更多關于Spring MVC 六 - DispatcherServlet處理請求過程的資料請關注腳本之家其它相關文章!
相關文章
spring boot中使用@Async實現(xiàn)異步調(diào)用任務
本篇文章主要介紹了spring boot中使用@Async實現(xiàn)異步調(diào)用任務,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-02-02SpringBoot啟動時自動執(zhí)行代碼的幾種實現(xiàn)方式
這篇文章主要給大家介紹了關于SpringBoot啟動時自動執(zhí)行代碼的幾種實現(xiàn)方式,文中通過實例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2022-02-02在navicat中導入mysql數(shù)據(jù)庫詳細步驟(即.sql后綴的數(shù)據(jù)庫)
Navicat是MySQL非常好用的可視化管理工具,功能非常強大,能滿足我們?nèi)粘?shù)據(jù)庫開發(fā)的所有需求,下面這篇文章主要給大家介紹了關于如何在navicat中導入mysql數(shù)據(jù)庫(即.sql后綴的數(shù)據(jù)庫)的相關資料,需要的朋友可以參考下2023-04-04Java利用happen-before規(guī)則如何實現(xiàn)共享變量的同步操作詳解
這篇文章主要給大家介紹了關于Java利用happen-before規(guī)則實現(xiàn)共享變量的同步操作的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用java具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2018-06-06SpringBoot使用MockMvc測試get和post接口的示例代碼
Spring Boot MockMvc是一個用于單元測試的模塊,它是Spring框架的一部分,專注于簡化Web應用程序的測試,MockMvc主要用來模擬一個完整的HTTP請求-響應生命周期,本文給大家介紹了SpringBoot使用MockMvc測試get和post接口,需要的朋友可以參考下2024-06-06Java實現(xiàn)RedisUtils操作五大集合(增刪改查)
本文主要介紹了Java實現(xiàn)RedisUtils操作五大集合,文中通過示例代碼介紹的非常詳細,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-07-07