【springMVC】springMVC學習系列一:springMVC的組件

系列文章目錄

前言

spring mvc 它解決了什么問題呢?
1.URL映射
2. 表單參數映射
3. 調用目標Control
4. 數據模型映射
5. 視圖解析
6. 異常處理
上述解決在spring mvc 中都體現在如下組件當中
HandlerMapping: url與控制器的映謝
HandlerAdapter: 控制器執行適配器
ViewResolver:視圖倉庫
view:具體解析視圖
HandlerExceptionResolver:異常捕捕捉器
HandlerInterceptor:攔截器

各組件調用關系流程圖如下:
在這里插入圖片描述

一、handler

真正處理請求的對象,有4種
1)實現了Controller接口的Bean對象
2)實現了HttpRequestHandler接口的Bean對象
3)@Controller注解的類中添加了@RequestMapping注解的方法(HandlerMethod)
4)HandlerFunction對象

其實handler是一個邏輯概念,并沒有一個統一的接口,上面4中對象都可以成為handler,代碼中是用Object來引用的,后面一篇會具體介紹

二、handlerMapping

有3種
1)BeanNameUrlHandlerMapping:負責Controller接口和HttpRequestHandler接口
2)RequestMappingHandlerMapping:負責@RequestMapping的方法
3)RouterFunctionMapping:負責RouterFunction以及其中的HandlerFunction

1.handlerMapping的重要結構

1)存儲請求和handler的映射關系
例如RequestMappingHandlerMapping存儲了2個map

a. mappingLookup:key:RequestMappingInfo value:HandlerMethod
RequestMappingInfo 是對@RequestMapping注解中元數據的封裝
HandlerMethod 是對method和目標對象的封裝,是處理器真正執行的地方

b. urlLookup:key:url value:List
url和RequestMappingInfo是多對多的關系,比如@RequestMapping 注解可以配置多個URL路徑來映射到同一個控制器方法

@Controller
public class MyController {@RequestMapping(value = {"/path1", "/path2", "/path3"})public String handleMultiplePaths() {return "viewName";}
}

一個URL可以通過請求方式映射多個控制器方法

@Controller
public class MyController {@RequestMapping(value = "/path",method = "GET")public String getResource() {return "viewName";}@RequestMapping(value = "/path",method = "POST")public String postResource() {return "viewName";}
}

至于具體怎么通過這2個map找到對應的處理器,下一篇再講

2)存儲攔截器
在處理請求時,與handler一起組成執行鏈executionChain

2.如何獲取handlerMapping

 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;

三、handlerAdapter

不同種類的Handler處理請求的方法不一樣,那么需要一個能將他們統一調用的東西,那就是適配器
針對不同的Handler,會有不同的適配器:
HttpRequestHandlerAdapter:對應實現了HttpRequestHandler的處理器
SimpleControllerHandlerAdapter:對應實現了Controller接口的處理器
RequestMappingHandlerAdapter:對應@RequestMapping注解方法的處理器
HandlerFunctionAdapter:對應實現了 HandlerFunction接口的處理器

尋找適配器的邏輯如下,也是策略模式

rotected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { if (this.handlerAdapters != null) { for (HandlerAdapter adapter : this.handlerAdapters) { if (adapter.supports(handler)) { return adapter; } } } 。。。}

四、HandlerMethodArgumentResolver

SpringMVC要去解析方法參數,那么該如何解析呢,是通過HandlerMethodArgumentResolver來進行的,比如對于@RequestMapping方法
RequestParamMethodArgumentResolver:負責處理@RequestParam
RequestHeaderMethodArgumentResolver:負責處理@RequestHeader
SessionAttributeMethodArgumentResolver:負責處理@SessionAttribute
RequestAttributeMethodArgumentResolver:負責處理@RequestAttribute
RequestResponseBodyMethodProcessor:負責處理@RequestBody

而在判斷某個參數該由哪個HandlerMethodArgumentResolver處理時,也是用的策略模式:

private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) { HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter); if (result == null) { for (HandlerMethodArgumentResolver resolver : this.argumentResolvers) { if (resolver.supportsParameter(parameter)) { result = resolver; this.argumentResolverCache.put(parameter, result); break; } } } return result; }

五、HandlerMethodReturnValueHandler

方法返回值如何解析呢,比如返回一個String,加了@ResponseBody注解直接將這個String返回給瀏覽器,沒有加就根據這個String找到對應的頁面,把頁面返回給瀏覽器。這些處理是通過HandlerMethodReturnValueHandler來進行的,比如下面的實現:
1)RequestResponseBodyMethodProcessor:處理加了@ResponseBody注解的情況
2)ViewNameMethodReturnValueHandler:處理沒有加@ResponseBody注解并且返回值類型為String的情況
3)ModelMethodProcessor:處理返回值是Model類型的情況

如何判斷使用哪個來解析呢,還是策略模式:

private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) {boolean isAsyncValue = isAsyncReturnValue(value, returnType);for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) {if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) {continue;}if (handler.supportsReturnType(returnType)) {return handler;}}return null;}

六、HttpMessageConverter

RequestResponseBodyMethodProcessor,因為它會處理加了@ResponseBody注解的情況,也是目前我們用得最多的情況。如果@ResponseBody注解的方法返回的不是String,而是Map、User對象呢,該怎么解析呢?
SpringMVC會利用HttpMessageConverter來處理,默認情況下有4種:
1)ByteArrayHttpMessageConverter:處理返回值為字節數組的情況,把字節數組返回給瀏覽器
2)StringHttpMessageConverter:處理返回值為字符串的情況,把字符串按指定的編碼序列號后返回給瀏覽器
3)SourceHttpMessageConverter:處理返回值為XML對象的情況,比如把DOMSource對象返回給瀏覽器
4)AllEncompassingFormHttpMessageConverter:處理返回值為MultiValueMap對象的情況

不過以上四個Converter是不能處理Map對象或User對象的,所以如果返回的是Map或User對象,那
么得單獨配置一個Converter,比如MappingJackson2HttpMessageConverter,這個Converter比
較強大,能把String、Map、User對象等等都能轉化成JSON格式。

public class AppConfig implements WebMvcConfigurer { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { MappingJackson2HttpMessageConverter messageConverter = new 
MappingJackson2HttpMessageConverter();messageConverter.setDefaultCharset(StandardCharsets.UTF_8); converters.add(messageConverter); } }

另外,如果使用StringHttpMessageConverter,字符集默認為ISO-8859-1,所以默認情況下返
回中文會亂碼,需要通過配置解決

ublic class AppConfig implements WebMvcConfigurer { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { 7StringHttpMessageConverter messageConverter = new 
StringHttpMessageConverter();messageConverter.setDefaultCharset(StandardCharsets.UTF_8); converters.add(messageConverter); } }

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/907175.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/907175.shtml
英文地址,請注明出處:http://en.pswp.cn/news/907175.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【Vue Vapor Mode :技術突破與性能優化的可能性】

Vue Vapor Mode &#xff1a;技術突破與性能優化的可能性 前言 作為一名有著Vue 2經驗和Vue 3經驗的開發者&#xff0c;你一定深刻體會過Vue從Options API到Composition API的演進&#xff0c;也感受過Vue 3在性能上相比Vue 2的顯著提升。現在&#xff0c;Vue團隊正在開發一個…

MySQL數據庫零基礎入門教程:從安裝配置到數據查詢全掌握【MySQL系列】

第1章&#xff1a;認識MySQL 1.1 什么是MySQL&#xff1f; MySQL是一種開源的關系型數據庫管理系統&#xff08;RDBMS&#xff09;&#xff0c;由瑞典MySQL AB公司開發&#xff0c;現由Oracle公司維護。它使用結構化查詢語言&#xff08;SQL&#xff09;進行數據庫的管理和操…

AXI3、AXI4 和 AXI5 的詳細差異對比

AXI3、AXI4 和 AXI5 的詳細差異對比 摘要&#xff1a;AXI (Advanced eXtensible Interface) 是 ARM 公司提出的高性能片上總線協議&#xff0c;廣泛用于 SoC (System on Chip) 設計中&#xff0c;以實現高效的數據傳輸和系統互連。AXI 協議隨著版本的迭代不斷演進&#xff0c;從…

向量數據庫該如何選擇?Milvus 、ES、OpenSearch 快速對比:向量搜索能力與智能檢索引擎的應用前景

? 1.milvus VS ES Milvus 的亮點 功能性&#xff1a;Milvus 不僅支持基本的向量相似性搜索&#xff0c;還支持稀疏向量、批量向量、過濾搜索和混合搜索功能等高級功能。 靈活性&#xff1a;Milvus 支持多種部署模式和多個 SDK&#xff0c;所有這些都在一個強大的集成生態系…

SQL進階之旅 Day 4:子查詢與臨時表優化

文章標題 【SQL進階之旅 Day 4】子查詢與臨時表優化 文章內容 開篇&#xff1a;SQL進階之旅的第4天 在“SQL進階之旅”系列中&#xff0c;第4天的主題是子查詢與臨時表優化。這是SQL開發中不可或缺的一部分&#xff0c;尤其在處理復雜查詢時&#xff0c;合理使用子查詢和臨…

Python學習(2) ----- Python的類型

在 Python 中&#xff0c;一切皆對象&#xff0c;每個對象都有類型。下面是 Python 中的常見內置類型分類和示例&#xff1a; &#x1f7e1; 1. 數字類型&#xff08;Numeric Types&#xff09; 類型說明示例int整數5, -42float浮點數3.14, -0.5complex復數1 2j a 10 …

跨協議協同智造新實踐:DeviceNet-EtherCAT網關驅動汽車焊接裝配效能躍遷

在汽車制造領域&#xff0c;機器人協作對于提升生產效率與產品質量至關重要。焊接、裝配等關鍵環節&#xff0c;需要機器人與各類設備緊密配合。JH-DVN-ECT疆鴻智能的devicenet從站轉ethercat主站協議網關&#xff0c;成為實現這一高效協作的得力助手&#xff0c;尤其是在連接歐…

nginx之proxy_buffering的作用

Nginx 的緩沖機制是為了讓后端能更快釋放資源&#xff0c;而不是卡在慢客戶端上&#xff0c;從而提升整體性能和并發能力。 現實中客戶端和后端服務器之間的傳輸速率可能差異很大。Nginx 的緩沖機制正是為了解決這個不匹配問題。 假設沒有緩沖&#xff08;即 proxy_buffering…

數據庫相關問題

1.保留字 1.1錯誤案例&#xff08;2025/5/27&#xff09; 報錯&#xff1a; java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near condition, sell…

GO 語言進階之 進程 OS與 編碼,數據格式轉換

更多個人筆記見&#xff1a; github個人筆記倉庫 gitee 個人筆記倉庫 個人學習&#xff0c;學習過程中還會不斷補充&#xff5e; &#xff08;后續會更新在github上&#xff09; 文章目錄 進程信息OS操作基本例子 編碼相關HASH 哈希Base64 encoding 基礎64編碼 數據格式轉換和處…

如何用Spring Cache實現對Redis的抽象

我們在進行Java項目開發時候&#xff0c;經常會用到Redis緩存例如數據庫里的一些信息、手機驗證碼之類的&#xff0c;正常寫法就會像去連mysql一樣&#xff0c;這種硬編碼的方式肯定是非常不合適的。 Autowireprivate UserMapper userMapper;Autowireprivate StringCommand str…

CMake指令:file()

目錄 1.簡介 2.常用子命令&#xff08;COMMAND&#xff09; 2.1.COPY - 復制文件或目錄 2.2.RENAME - 重命名文件或目錄 2.3.REMOVE - 刪除文件或目錄 2.4.MAKE_DIRECTORY - 創建目錄 2.5.READ - 讀取文件內容 2.6.WRITE - 寫入文件內容 2.7.GLOB - 按模式匹配文件 2…

使用VuePress開發日志

結合官方教程&#xff0c;補充一些細節。 快速上手 | VuePress中文文檔 | VuePress中文網 VuePress使用步驟 創建并進入一個新目錄 mkdir vuepress-starter && cd vuepress-starter使用你喜歡的包管理器進行初始化 yarn init # npm init將 VuePress 安裝為本地依賴 …

隨手記錄7

2025年5月26日~2025年6月01日 周一&#xff1a;沒做 周二&#xff1a;芹菜炒雞蛋香腸 周三&#xff1a; 周四&#xff1a; 周五&#xff1a; 周六&#xff1a; 周日&#xff1a;

【無標題】使用JEasyOpc開發OPCDA采集中間件

使用JEasyOpc開發OPCDA采集中間件 1.JEasyOpc下載2.修改JEasyOpc源碼及打包安裝3.Pom 引入jeasy2.3.2.jar4.maven pom 配置打包5.cmd執行&#xff08;手動指定 main主程序入口&#xff09;6.EXE4J打包jar包&#xff0c;生成exe可執行文件 1.JEasyOpc下載 jeasyopc源碼下載&…

5 WPF中的Page頁面的使用

以下是一個簡單的WPF示例&#xff0c;演示如何在三個Page之間進行導航切換&#xff0c;使用Frame控件作為導航容器&#xff0c;并包含基本的導航按鈕&#xff08;前進/后退/主頁&#xff09; Page類更簡單&#xff0c;比Window更精簡。 代碼見下文以及資源文件&#xff1a; htt…

基于51單片機的音樂盒點陣屏proteus仿真

地址&#xff1a; https://pan.baidu.com/s/1hYzg2icjHV8jWJdltJkKxw 提取碼&#xff1a;1234 仿真圖&#xff1a; 芯片/模塊的特點&#xff1a; AT89C52/AT89C51簡介&#xff1a; AT89C51 是一款常用的 8 位單片機&#xff0c;由 Atmel 公司&#xff08;現已被 Microchip 收…

圖論:floyed算法

Floyd 算法是一種用于尋找加權圖中所有頂點對之間最短路徑的經典算法&#xff0c;它能夠處理負權邊&#xff0c;但不能處理負權環。即如果邊權有負數&#xff0c;切負權邊與其他邊構成了環就不能用該算法。該算法的時間復雜度為 \(O(V^3)\)&#xff0c;其中 V 是圖中頂點的數量…

STM32之看門狗(IWDG)

一、看門狗外設的原理與應用 背景說明 隨著單片機的發展&#xff0c;單片機在家用電器、工業自動化、生產過程控制、智能儀器儀表等領域的應用越來越廣泛。然而處于同一電力系統中的各種電氣設備通過電或磁的聯系彼此緊密相連&#xff0c;相互影響&#xff0c;由于運行方式的…

#RabbitMQ# 消息隊列進階

目錄 消息可靠性 一 生產者的可靠性 1 生產者的重連 2 生產者的確認 (1 Confirm* (2 Return 二 MQ的可靠性 1 數據持久化 2 Lazy Queue* 三 消費者的可靠性 1 消費者確認機制 2 消費失敗處理 3 業務冪等性 四 延遲消息 消息可靠性 在消息隊列中&#xff0c;可靠性…