Spring MVC核心組件與請(qǐng)求處理流程分析
Spring MVC請(qǐng)求處理完整流程詳解
一、流程文字描述
當(dāng)一個(gè)HTTP請(qǐng)求到達(dá)服務(wù)器后,會(huì)經(jīng)歷以下流程:
Filter鏈處理(入口)
- 請(qǐng)求首先經(jīng)過Filter鏈
- 每個(gè)Filter按照定義的順序執(zhí)行doFilter方法的前置處理
- Filter通過調(diào)用chain.doFilter()將請(qǐng)求傳遞給下一個(gè)Filter
DispatcherServlet接收請(qǐng)求
- 所有Filter處理完后,請(qǐng)求到達(dá)DispatcherServlet
- DispatcherServlet作為前端控制器,統(tǒng)一處理所有請(qǐng)求
尋找Handler
- DispatcherServlet調(diào)用getHandler方法
- 遍歷所有HandlerMapping,找到與當(dāng)前URL匹配的Handler
- 找到Handler后,把Handler和對(duì)應(yīng)的攔截器封裝成HandlerExecutionChain對(duì)象
獲取HandlerAdapter
- 根據(jù)Handler的類型,遍歷所有HandlerAdapter
- 找到支持該Handler類型的HandlerAdapter
- HandlerAdapter用于調(diào)用Handler并處理參數(shù)、返回值等
攔截器前置處理
- 按順序調(diào)用HandlerExecutionChain中所有攔截器的preHandle方法
- 如果任一攔截器的preHandle返回false,則中斷請(qǐng)求處理
- 中斷時(shí)會(huì)觸發(fā)已執(zhí)行的攔截器的afterCompletion方法
Handler處理請(qǐng)求
- 通過HandlerAdapter調(diào)用Handler(Controller方法)
- HandlerAdapter負(fù)責(zé)參數(shù)解析、類型轉(zhuǎn)換
- Handler執(zhí)行業(yè)務(wù)邏輯,返回處理結(jié)果
攔截器后置處理
- Handler執(zhí)行完成后,按逆序調(diào)用所有攔截器的postHandle方法
- 此時(shí)視圖尚未渲染
視圖渲染
- 根據(jù)Handler返回的結(jié)果進(jìn)行視圖渲染
- 如果是@RestController,將返回值轉(zhuǎn)換為JSON/XML等格式
- 如果是傳統(tǒng)@Controller,解析視圖名稱并渲染視圖
攔截器完成處理
- 視圖渲染完成后,按逆序調(diào)用所有攔截器的afterCompletion方法
- 無論過程中是否有異常,都會(huì)執(zhí)行afterCompletion
Filter鏈處理(出口)
- 響應(yīng)會(huì)按照與處理請(qǐng)求相反的順序經(jīng)過Filter鏈
- 每個(gè)Filter執(zhí)行doFilter方法的后置處理
- 最終響應(yīng)返回給客戶端
二、關(guān)鍵組件詳解
2.1 HandlerMapping
// 核心數(shù)據(jù)結(jié)構(gòu) public class RequestMappingHandlerMapping { // 保存URL與處理器方法的映射關(guān)系 private final Map<RequestMappingInfo, HandlerMethod> mappingLookup; } // 映射示例 mappingLookup = { RequestMappingInfo{ patterns=/users/{id}, // URL模式 methods=GET, // HTTP方法 params=[], // 請(qǐng)求參數(shù) headers=[] // 請(qǐng)求頭 } -> HandlerMethod{UserController.getUser()} }
2.2 HandlerExecutionChain
public class HandlerExecutionChain { // Handler本身(如Controller的方法) private final Object handler; // 與Handler關(guān)聯(lián)的攔截器列表 private List<HandlerInterceptor> interceptors; }
2.3 HandlerAdapter
// 處理@RequestMapping注解的方法 public class RequestMappingHandlerAdapter implements HandlerAdapter { public ModelAndView handle(request, response, handler) { // 1. 解析請(qǐng)求參數(shù) Object[] args = resolveParameters(request, handler); // 2. 調(diào)用Controller方法 Object returnValue = invokeMethod(handler, args); // 3. 處理返回值 return processReturnValue(returnValue); } }
2.4 視圖渲染
// 1. @RestController(JSON渲染) @GetMapping("/api/user") public User getUser() { return user; // 自動(dòng)轉(zhuǎn)換為JSON } // 2. @Controller(HTML渲染) @GetMapping("/user") public String user(Model model) { model.addAttribute("user", user); return "userView"; // 解析為具體視圖 }
三、攔截器執(zhí)行流程
3.1 攔截器定義
public class LogInterceptor implements HandlerInterceptor { @Override public boolean preHandle(request, response, handler) { System.out.println("LogInterceptor - preHandle"); return true; } @Override public void postHandle(request, response, handler, mv) { System.out.println("LogInterceptor - postHandle"); } @Override public void afterCompletion(request, response, handler, ex) { System.out.println("LogInterceptor - afterCompletion"); } }
3.2 執(zhí)行順序示例
Filter1 - 請(qǐng)求處理 Filter2 - 請(qǐng)求處理 LogInterceptor - preHandle SecurityInterceptor - preHandle Controller方法執(zhí)行 SecurityInterceptor - postHandle LogInterceptor - postHandle 視圖渲染 SecurityInterceptor - afterCompletion LogInterceptor - afterCompletion Filter2 - 響應(yīng)處理 Filter1 - 響應(yīng)處理
3.3 攔截器調(diào)用過程
// 1. preHandle調(diào)用(正序) for (HandlerInterceptor interceptor : interceptors) { if (!interceptor.preHandle(request, response, handler)) { triggerAfterCompletion(request, response, handler, null); return false; } } // 2. postHandle調(diào)用(逆序) for (int i = interceptors.length - 1; i >= 0; i--) { interceptors[i].postHandle(requestresponse, handler, mv); } // 3. afterCompletion調(diào)用(逆序) for (int i = interceptors.length - 1; i >= 0; i--) { interceptors[i].afterCompletion(request, response, handler, ex); }
到此這篇關(guān)于Spring MVC核心組件與請(qǐng)求處理流程的文章就介紹到這了,更多相關(guān)Spring MVC請(qǐng)求處理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springcloud gateway如何配置動(dòng)態(tài)路由
本文主要介紹了在SpringCloudGateway中配置動(dòng)態(tài)路由的步驟,包括引入依賴、配置路由源、添加配置中心依賴、配置配置中心、定義路由規(guī)則和刷新配置等內(nèi)容,使路由規(guī)則在配置中心更新時(shí),無需重啟網(wǎng)關(guān)服務(wù)即可動(dòng)態(tài)應(yīng)用新的路由規(guī)則2024-10-10Java+JFrame實(shí)現(xiàn)貪吃蛇小游戲
這篇文章主要為大家詳細(xì)介紹了Java+JFrame實(shí)現(xiàn)貪吃蛇小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06springboot內(nèi)嵌Tomcat安全漏洞修復(fù)方式
針對(duì)CVE-2020-1938漏洞,建議升級(jí)Tomcat至安全版本以避免受影響,影響版本包括:Apache Tomcat 9.x小于9.0.31、Apache Tomcat 8.x小于8.5.51、Apache Tomcat 7.x小于7.0.100及Apache Tomcat 6.x,2024-10-10通過實(shí)例解析spring環(huán)繞通知原理及用法
這篇文章主要介紹了通過實(shí)例解析spring環(huán)繞通知原理及用法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10idea中maven本地倉庫jar包打包失敗和無法引用的問題解決
本文主要介紹了idea中maven本地倉庫jar包打包失敗和無法引用的問題解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06解決IDEA中多模塊下Mybatis逆向工程不生成相應(yīng)文件的情況
這篇文章主要介紹了解決IDEA中多模塊下Mybatis逆向工程不生成相應(yīng)文件的情況,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-01-01IDEA?Ui設(shè)計(jì)器JFormDesigner?永久激活插件+注冊(cè)機(jī)(親測(cè)一直在用)
這篇文章主要介紹了IDEA?Ui設(shè)計(jì)器JFormDesigner?永久激活----插件+注冊(cè)機(jī)?自己一直在用的版本和注冊(cè)機(jī),非常不錯(cuò),本文通過圖文并茂的形式給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-08-08