SpringBoot-Web開發-內容協商——多端內容適配內容協商原理HttpMessageConverter

其它篇章:
一:SpringBoot3-日志——日志原理&日志格式&日志級別&日志分組&文件輸出&文件歸檔&滾動切割
二:SpringBoot3-Web開發-靜態資源——WebMvcAutoConfiguration原理&資源映射&資源緩存&歡迎頁&Favicon&自定義

一、多端內容適配

一套系統適配多端數據返回。

假設:
  • 主體:寫好一個接口GET /person
  • 部署:部署到服務器,暴露給外界訪問。
  • 外界
    1. 一個移動端應用:希望接口返回一個JSON文件;
    2. 一個第三方應用:希望接口返回一個XML文件;
    3. 一個IoT(物聯網設備):希望接口返回一個自定義協議數據文件。
提問:
  • 以以上假設為例,如何讓一個接口做到多端的數據反饋?
思考:
  • ,可以寫三個請求路徑,分別為/person.json/person.xml/person.diy(應用指定后綴),這三個不同應用分別訪問指定的請求路徑:
    • 缺點:這種方法只能用在內部接口少的情況下。如果,內部接口很多,那么每個接口都得拆分成三個接口,對應三個外部應用。若需要返回更多種類型數據文件,這個數量還得上升。
  • SpringBoot可以解決這個問題,詳細看接下來的內容。

默認規則

a.主要內容

內容協商功能是SpringMVC自帶的功能,SpringBoot對其進行了整合,快速實現一套系統適配多端數據返回。

SpringBoot多端內容適配
  1. 基于請求頭內容協商(默認開啟)
  • 客戶端服務端 發送請求時,攜帶HTTP標準的Accept請求頭。
    • 客戶端:外界應用
    • 服務端:接口
    • accept:是http協議里規定的一個標準
  • 客戶端服務端 發送請求時,帶上Accept,讓 服務端 知道該返回什么類型的數據,SpringBoot 就把數據自動格式化成對應類型,再返回。
    • 舉例
      • Accept:application/json
      • Accept:text\xml
      • Accept:text\yaml
  1. 基于請求參數內容協商(需要手動開啟)
  • 舉例
    • ?format=json:
      • 發送請求: GET /projects/spring-boot?format=json
      • 匹配:匹配到 GetMapping("/projects/spring-boot")
      • 返回:根據參數協商,優先返回json類型數據
    • 同理,發送請求 GET /projects/spring-boot?format=xml,則優先返回xml類型數據

b.演示驗證

  1. 創建一個接口,其內容如下:
    • 先綁定地址:@GetMapping("/person")
    • 再定義一個 Person類。
    • 創建的接口代碼如下:
      package com.atwyb.web.controller;import com.atwyb.web.bean.Person;
      import org.springframework.web.bind.annotation.GetMapping;
      import org.springframework.web.bind.annotation.RestController;@RestController
      public class HelloController {@GetMapping("/person")public Person person(){Person person = new Person();person.setId("1");person.setUserName("zhangsan");return person;}
      }
      
    • person的javabean如下:
      package com.atwyb.web.bean;public class Person {private String id;private String userName;public String getId() {return id;}public void setId(String id) {this.id = id;}public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}
      }
      

點進@RestController,發現標注了@ResponseBody。說明@RestController返回的數據都標注了@ResponseBody,而所有標注了@ResponseBody的對象,都會以json傳輸。
在這里插入圖片描述

  1. 啟動項目,在瀏覽器中驗證:

    • 瀏覽器中訪問:http://localhost:8080/person
    • 發現數據的類型為json,如下圖所示:在這里插入圖片描述
  2. 思考:要想讓數據適配xml,該怎么做?

    • SpringBoot默認支持把對象寫為json。因為默認web場景導入了jackson處理json的包:jackson-core。
    • jackson是一個庫,也支持把數據寫為xml,但要導入xml相關依賴:
      • 引入支持xml內容依賴:
         <dependency><groupId>com.fasterxml.jackson.dataformat</groupId><artifactId>jackson-dataformat-xml</artifactId>
        </dependency>
        
      • 標注xml注解:在Person這個JavaBean下標注xml注解
        @JacksonXmlRootElement
        public class person{(省略……)}
        
    • 開啟基于請求參數的內容協商(默認關閉)
      • 開啟基于請求參數的內容協商功能,默認參數名為format
        spring.mvc.contentnegotiation.favor-parameter=true
        
      • 指定內容協商時使用的參數名,默認為format
      • 在application.propertise中添加以下內容:
        在這里插入圖片描述
  3. 驗證:

    • 在瀏覽器中訪問http://localhost:8080/person?format=xml
      在這里插入圖片描述
    • 在瀏覽器中訪問http://localhost:8080/person?type=json在這里插入圖片描述

二、內容協商原理-HttpMessageConverter

學習邏輯鏈:

  1. 目的:想要自定義接口的返回內容
  2. 分析:要想自定義接口的返回內容,就要先理解內容協商的底層原理;而要理解內容協商的底層原理,只要知道HttpMessageConverter怎么工作,什么時候工作就行了;知道HttpMessageConverter工作原理后,就能通過定制HttpMessageConverter來實現多端內容協商,以達到自定義接口返回內容的目的。
  3. 步驟:
    a. 了解HttpMessageConverter怎么工作,什么時候工作。
    b. 這樣就能,理解內容協商的底層原理
    c. 接下來就能,通過定制HttpMessageConverter來實現多端內容協商。
    d. 這樣就,達到了想要自定義接口的返回內容的目的。
  4. 總結:要想知道怎么自定義接口的返回內容,其實就是要知道怎么通過定制HttpMessageConverter來實現多端內容協商。

WebMvcConfigurer接口里,能夠配置很多底層的東西,其中就包含了一個configureMessageConverters,如下圖。
在這里插入圖片描述
只需要編寫WebMvcConfigurer接口提供的configureMessageConverters底層,修改底層的MessageConverters就可以了。
思考:只要修改以上的MessageConverters就可以了,但為什么這樣做就可以了?這就是接下來要說的內容了。

1、@ResponseBody由HttpMessageConverter處理

a.主要內容

在向瀏覽器返回內容的controller里,有一個@RestController注解,而這個注解里又包含一個@ResponseBody,而注解標注在類上面,就表示標注在每一個方法上。

  1. 如果controller方法的返回值標注了@ResponseBody注解,
    按照SpringMVC的原理,我們從DispatcherServlet.class開始,所有請求來到DispatcherServlet,都是從doDispatch()開始的。
    ctlr+n搜索DispatcherServlet.class,進入后繼續ctlr+n搜索doDispatch(),在其內容第一行設置一個斷點,找到以下界面:
    在這里插入圖片描述
    往下翻找到HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
    在這里插入圖片描述
  2. 如果根據/person這個請求路徑找到了某個方法要處理,那就要找到這個適配器,最終利用這個適配器處理方法。往下翻找到mv = ha.handle(processedRequest, response, mappedHandler.getHandler());,如圖。這是正真執行handler的語句。
    在這里插入圖片描述
  3. 給person()第一行打個斷點,并以debug啟動,看看是怎么處理的。
    在這里插入圖片描述
    瀏覽器訪問http://localhost:8080/person?format=json,先來到doDispatch,它來接第一個請求。在這里插入圖片描述
    放行。
    在這里插入圖片描述
    再放行,來到正真執行handler的語句的位置。
    在這里插入圖片描述
  4. 這個時候點擊step into,進到這個目標執行方法,來到以下界面:
    在這里插入圖片描述
    再點進handleInternal,往下翻,看到invokeHandlerMethod方法。
    在這里插入圖片描述
    點進去,在第一行設置一個斷點:
    在這里插入圖片描述
    一直放行到這,目標方法還沒進行到,只進行到invokeHandlerMethod
    RequestMappingHandlerAdapter.class中往下找到invocableMethod.invokeAndHandle,意思是執行并處理,把這一放行,就會去到person()并執行。在這里插入圖片描述
    這樣就會得到結論:
    RequestMappingHandlerAdapter.class里面的invokeAndHandle()才是正真執行目標方法的。

b. 總結:

  • 如果controller方法的返回值標注了@ResponseBody注解:
    1. 請求進來先來到DispatcherServletdoDispatch()進行處理
    2. 找到一個HandlerAdapter適配器,利用適配器執行目標方法
    3. RequestMappingHandlerAdapter來執行,調用invokeHandlerMethod()來執行目標方法
    4. 目標方法執行之前,準備好兩個東西:
      • HandlerMethodArgumentResolver:參數解析器,確定目標方法每個參數值
      • HandlerMethodReturnValueHandler:返回值處理器,確定目標方法的返回值該怎么處理。
    5. 目標方法執行完成,會返回返回值對象
    6. 找到一個合適的返回值處理器
    7. 最終找到RequestResponseBodyMethodProcessor中能處理 標注了@ResponseBody注解 的方法
    8. RequestResponseBodyMethodReturnValueHandler調用writeWithMessageConverters,利用MessageConverter把返回值寫出去。

看到@GetMapping,要知道這個注解都是由invokeHandlerMethod所在的RequestMappingHandlerAdapter.class

其它篇章:
一:SpringBoot3-日志——日志原理&日志格式&日志級別&日志分組&文件輸出&文件歸檔&滾動切割
二:SpringBoot3-Web開發-靜態資源——WebMvcAutoConfiguration原理&資源映射&資源緩存&歡迎頁&Favicon&自定義

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

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

相關文章

Spring MVC 類型轉換與參數綁定:從架構到實戰

在 Spring MVC 開發中&#xff0c;“前端請求數據” 與 “后端 Java 對象” 的格式差異是高頻痛點 —— 比如前端傳的String類型日期&#xff08;2025-09-08&#xff09;要轉成后端的LocalDate&#xff0c;或者字符串male要轉成GenderEnum.MALE枚舉。Spring 并非通過零散工具解…

Spark提交任務的資源配置和優化

Spark 提交任務時主要可調的資源配置參數包括 Driver 資源&#xff08;內存、CPU&#xff09;、Executor 資源&#xff08;數量、內存、CPU&#xff09;以及 集群管理相關參數。配置和優化時一般結合集群硬件資源、數據規模、作業類型和作業復雜度&#xff08;SQL / 機器學習&a…

機器學習06——支持向量機(SVM核心思想與求解、核函數、軟間隔與正則化、支持向量回歸、核方法)

上一章&#xff1a;機器學習05——多分類學習與類別不平衡 下一章&#xff1a;機器學習07——貝葉斯分類器 機器學習實戰項目&#xff1a;【從 0 到 1 落地】機器學習實操項目目錄&#xff1a;覆蓋入門到進階&#xff0c;大學生就業 / 競賽必備 文章目錄一、間隔與支持向量&…

AI集群全鏈路監控:從GPU微架構指標到業務Metric關聯

點擊 “AladdinEdu&#xff0c;同學們用得起的【H卡】算力平臺”&#xff0c;H卡級別算力&#xff0c;80G大顯存&#xff0c;按量計費&#xff0c;靈活彈性&#xff0c;頂級配置&#xff0c;學生更享專屬優惠。 引言&#xff1a;AI算力時代的監控挑戰 隨著深度學習模型規模的指…

K8s Ingress Annotations參數使用指南

Kubernetes Ingress Annotations 是與特定 Ingress 控制器&#xff08;如 Nginx、Traefik、HAProxy 等&#xff09;配合使用&#xff0c;用于擴展和定制 Ingress 資源行為的關鍵配置項。它們通常以鍵值對的形式添加在 Ingress 資源的 metadata部分。Ingress Annotations參數速查…

CodeBuddy Code深度實戰:從零構建智能電商推薦系統的完整開發歷程

項目背景與挑戰作為一名有著多年全棧開發經驗的技術人員&#xff0c;我最近接手了一個具有挑戰性的項目&#xff1a;為某中型服裝電商平臺開發一套智能商品推薦系統。該系統需要在2個月內完成&#xff0c;包含以下核心功能&#xff1a;前端&#xff1a;React TypeScript構建的…

Day 19: 算法基礎與面試理論精通 - 從思想理解到策略掌握的完整體系

Day 19: 算法基礎與面試理論精通 - 從思想理解到策略掌握的完整體系 ?? 課程概述 核心目標:深度理解算法設計思想和核心原理,掌握面試高頻算法概念,建立完整的算法知識體系 學習重點: ? 核心數據結構的本質理解和應用場景分析 ? 經典算法設計模式的思想精髓和解題策…

AI與AR融合:重塑石化與能源巡檢的未來

在石化企業和新能源電站的巡檢工作中&#xff0c;傳統模式正被一場技術革命所顛覆。AI與AR&#xff08; www.teamhelper.cn &#xff09;的深度融合&#xff0c;不僅提升了巡檢效率&#xff0c;更將巡檢工作從被動響應轉變為預測預防&#xff0c;開啟了智能運維的新篇章。一、透…

滴滴二面(準備二)

手寫防抖函數并清晰闡述其價值&#xff0c;確實是前端面試的常見考點。下面我將為你直接呈現防抖函數的代碼&#xff0c;并重點結合滴滴的業務場景進行解釋&#xff0c;幫助你向面試官展示思考深度。 這是防抖函數的一個基本實現&#xff0c;附帶注釋以便理解&#xff1a; func…

Kubernetes(四):Service

目錄 一、定義Service 1.1 typeClusterIP 1.2 typeNodePort 1.3 typeLoadBalancer 1.4 typeExternalName 1.5 無標簽選擇器的Service 1.6 Headless Service 二、Kubernetes的服務發現 2.1 環境變量方式 2.2 DNS方式 Kubernetes 中 Service 是 將運行在一個或一組 Pod 上的應用…

在 Python 中實現觀察者模式的具體步驟是什么?

在 Python 中實現觀察者模式可以遵循以下具體步驟&#xff0c;這些步驟清晰地劃分了角色和交互流程&#xff1a; 步驟 1&#xff1a;定義主題&#xff08;Subject&#xff09;基類 主題是被觀察的對象&#xff0c;負責管理觀察者和發送通知。需實現以下核心方法&#xff1a; 存…

分布式方案 一 分布式鎖的四大實現方式

Java分布式鎖實現方式詳解 什么是分布式鎖 基于數據庫的分布式鎖基于Redis的分布式鎖基于ZooKeeper的分布式鎖基于Etcd的分布式鎖 各種實現方式對比最佳實踐建議多節點/線程調用結果展示 基于數據庫的分布式鎖 - 多線程測試基于Redis的分布式鎖 - 多節點測試基于ZooKeeper的分…

基于Room+RESTful的雙權限Android開機時間監控方案

概述 以下是使用Kotlin實現的商業級Android開機時間記錄功能&#xff0c;包含現代Android開發最佳實踐。 系統架構 組件設計 // BootReceiver - 接收開機廣播 class BootReceiver : BroadcastReceiver() {override fun onReceive(context: Context, intent: Intent?) {if (int…

水庫大壩安全監測系統的作用

水庫大壩作為重要的水利基礎設施&#xff0c;承擔著防洪、供水、發電、灌溉等多重功能&#xff0c;其安全性直接關系到人民生命財產安全和社會經濟發展。然而&#xff0c;由于自然環境變化、材料老化、荷載作用以及人為因素的影響&#xff0c;大壩在長期運行過程中可能出現裂縫…

《Kubernetes 構建 MySQL MGR 集群實戰教程》

#### 一、前言 MySQL Group Replication (MGR) 是 MySQL 官方提供的高可用集群方案&#xff0c;基于 Paxos 協議實現多節點數據強一致性。本教程將指導如何在 Kubernetes 上部署 MySQL MGR 集群&#xff0c;適用于生產級高可用場景。---#### 二、環境準備 1. **Kubernetes 集…

影視APP源碼 SK影視 安卓+蘋果雙端APP 反編譯詳細視頻教程+源碼

內容目錄一、詳細介紹二、效果展示1.部分代碼2.效果圖展示三、學習資料下載一、詳細介紹 影視APP源碼 SK影視 安卓蘋果雙端APP 反編譯詳細視頻教程源碼 自帶對接優效SDK廣告&#xff08;已失效&#xff09;。域名和IP都可以搭建。 自帶一起看和短劇頁面功能&#xff0c;三種…

pyqt+python之二進制生肖占卜

目錄 一、引言 二、GUI界面設計 1.效果演示 2.相關提示 3.界面設計.py 三、主要程序詳解 1.導入相關模塊 2.初始化設置 3.組內判斷 4.猜測過程 四、總程序代碼 一、引言 在數字時代&#xff0c;傳統文化與編程語言的碰撞總能迸發奇妙火花。本項目以PyQtPython為技術…

人工智能-python-深度學習-經典網絡模型-LeNets5

文章目錄LeNet-5&#xff08;詳解&#xff09;—— 從原理到 PyTorch 實現&#xff08;含訓練示例&#xff09;簡介LeNet-5 的核心思想LeNet-5 逐層結構詳解逐層計算舉例&#x1f4cc; 輸入層&#x1f4cc; C1 卷積層&#x1f4cc; S2 池化層&#x1f4cc; C3 卷積層&#x1f4…

機器視覺的手機柔性屏貼合應用

在智能手機制造領域&#xff0c;柔性屏逐漸成為智能手機的主流選擇&#xff0c;柔性屏因其輕便、易于彎曲的特性&#xff0c;已成為現代電子設備的重要組成部分&#xff0c;但同時也帶來了前所未有的制造挑戰。柔性屏與傳統剛性玻璃屏有本質區別&#xff0c;它容易形變&#xf…

貪心算法應用:數字孿生同步問題詳解

Java中的貪心算法應用&#xff1a;數字孿生同步問題詳解 貪心算法是一種在每一步選擇中都采取在當前狀態下最好或最優&#xff08;即最有利&#xff09;的選擇&#xff0c;從而希望導致結果是全局最好或最優的算法。下面我將全面詳細地講解貪心算法在數字孿生同步問題中的應用。…