Spring MVC @RequestHeader 注解怎么用?

我們來詳細解釋一下 Spring MVC 中的 @RequestHeader 注解。

@RequestHeader 注解的作用

@RequestHeader 注解用于將 HTTP 請求中的**請求頭(Request Headers)**的值綁定到 Controller 方法的參數上。

請求頭是 HTTP 請求的一部分,包含了關于請求本身、客戶端、期望的響應格式等元數據信息。常見的請求頭有 User-Agent(瀏覽器/客戶端信息)、Accept(客戶端可接受的內容類型)、Content-Type(請求體的類型)、Authorization(認證信息)、Accept-Language(語言偏好)以及各種自定義頭(通常以 X- 開頭,如 X-API-Key)。

@RequestHeader 允許我們在 Controller 方法中訪問這些頭信息。

基本用法

最直接的用法是指定要讀取的請求頭的名稱,并將其值賦給方法參數。

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.ResponseBody;@Controller
public class HeaderController {// 讀取 "User-Agent" 請求頭@GetMapping("/show-user-agent")@ResponseBodypublic String showUserAgent(@RequestHeader("User-Agent") String userAgent) {return "User-Agent Header is: " + userAgent;}// 讀取 "Accept-Language" 請求頭@GetMapping("/show-language")@ResponseBodypublic String showAcceptLanguage(@RequestHeader("Accept-Language") String language) {return "Accepted Languages: " + language;}// 讀取自定義請求頭 "X-Custom-Header"@GetMapping("/show-custom-header")@ResponseBodypublic String showCustomHeader(@RequestHeader("X-Custom-Header") String customHeaderValue) {return "X-Custom-Header value: " + customHeaderValue;}
}

重要: HTTP 協議中請求頭名稱是大小寫不敏感的。然而,在 @RequestHeader 注解中指定的名稱("User-Agent", "Accept-Language")會與實際發送的頭名稱進行不區分大小寫的匹配。但為了代碼清晰和避免潛在問題,最好在注解中明確使用期望的、標準的頭名稱

@RequestHeader 的屬性

@RequestParam 類似,@RequestHeader 也提供了一些屬性來定制行為:

  1. name (或 value):

    • 必需屬性(除非參數名匹配)。指定要綁定的請求頭的名稱。這是最常用的屬性。
    • namevalue 是同義詞。
    • 示例:@RequestHeader(name = "Authorization") String token
    • 注意:雖然理論上如果方法參數名與頭名稱(轉換為駝峰式,例如 userAgent 對應 User-Agent)匹配,可能可以省略 name,但這依賴于編譯時參數名保留,并且對于包含 - 的標準頭名稱(如 User-Agent)根本行不通。因此,強烈建議始終使用 namevalue 屬性明確指定頭名稱
  2. required:

    • 指定該請求頭是否必須存在于請求中。
    • 類型:boolean
    • 默認值:true。如果 required=true,但請求中沒有該頭信息,Spring MVC 會拋出 MissingRequestHeaderException 異常,導致 HTTP 400 (Bad Request) 響應。
    • 如果請求頭是可選的,需要設置為 required = false
  3. defaultValue:

    • 當請求中沒有提供該請求頭時,為其提供一個默認值。
    • 類型:String。Spring 會嘗試將這個字符串默認值轉換為方法參數的目標類型(盡管對于Header,目標類型通常就是 String)。
    • 注意: 使用 defaultValue 隱含了 required = false 的行為。提供了 defaultValue 后,即使不顯式設置 required = false,該頭也不再是必需的。如果頭不存在,就會使用默認值,不會拋出異常。

處理可選請求頭和默認值

場景 1:請求頭可選,如果不存在則為 null

import java.util.Optional;
// ...@GetMapping("/optional-header")
@ResponseBody
public String processOptionalHeader(@RequestHeader(name = "X-Optional-Info", required = false) String optionalInfo,@RequestHeader(name = "X-Another-Optional", required = false) Optional<String> anotherOptional) {String infoMessage = (optionalInfo != null) ? "X-Optional-Info: " + optionalInfo : "X-Optional-Info header is missing";String anotherMessage;if (anotherOptional.isPresent()) {anotherMessage = "X-Another-Optional: " + anotherOptional.get();} else {anotherMessage = "X-Another-Optional header is missing";}return infoMessage + "\n" + anotherMessage;
}
// 請求 /optional-header (無對應Header) -> 輸出兩條 "header is missing"
// 請求 /optional-header 且帶 Header X-Optional-Info: hello -> 輸出 "X-Optional-Info: hello" 和另一條 missing
// 請求 /optional-header 且帶 Header X-Another-Optional: world -> 輸出第一條 missing 和 "X-Another-Optional: world"
  • 使用 required = false,如果 Header 不存在,對應的 String 參數會是 null
  • 使用 Optional<String> (Spring 4.1+) 也可以處理可選值。

場景 2:請求頭可選,如果不存在則使用默認值

@GetMapping("/theme")
@ResponseBody
public String getTheme(@RequestHeader(name = "X-Theme-Preference", defaultValue = "light") String theme) {// 如果請求中沒有 X-Theme-Preference 頭,theme 的值將是 "light"// 如果請求頭是 X-Theme-Preference: dark,theme 的值將是 "dark"return "Using theme: " + theme;
}

處理多值請求頭

有些請求頭可能包含多個值(通常是逗號分隔的,如 Accept 頭)。我們可以將方法參數聲明為 List 或數組類型來接收所有值。

import java.util.List;
// ...@GetMapping("/accepted-types")
@ResponseBody
public String showAcceptedTypes(@RequestHeader("Accept") String[] acceptTypes) {// 如果 Accept 頭是 "application/json, application/xml", acceptTypes 會是 ["application/json", "application/xml"]return "Client accepts: " + Arrays.toString(acceptTypes);
}@GetMapping("/cache-control")
@ResponseBody
public String showCacheControl(@RequestHeader("Cache-Control") List<String> cacheDirectives) {// 如果 Cache-Control 頭是 "no-cache, no-store", cacheDirectives 會是 ["no-cache", "no-store"]return "Cache-Control directives: " + cacheDirectives;
}

Spring 會自動根據逗號 , 來分割頭的值。

綁定所有請求頭到 Map 或 HttpHeaders

如果我們想訪問請求中的所有頭信息,可以將 @RequestHeader 應用于 Map<String, String>MultiValueMap<String, String>HttpHeaders 對象。

import org.springframework.http.HttpHeaders;
import org.springframework.util.MultiValueMap;
import java.util.Map;
// ...@GetMapping("/all-headers-map")
@ResponseBody
public String getAllHeadersMap(@RequestHeader Map<String, String> headers) {// headers 包含所有請求頭的 key-value 對 (key 是小寫形式)// 注意: 如果一個頭有多個值, Map 可能只保留一個return "All headers (Map): " + headers.toString();
}@GetMapping("/all-headers-multimap")
@ResponseBody
public String getAllHeadersMultiMap(@RequestHeader MultiValueMap<String, String> headers) {// MultiValueMap 可以正確處理一個頭有多個值的情況 (key 是小寫形式)return "All headers (MultiValueMap): " + headers.toString();
}@GetMapping("/all-headers-object")
@ResponseBody
public String getAllHeadersObject(@RequestHeader HttpHeaders headers) {// HttpHeaders 是 Spring 提供的專用對象,提供了方便的方法來訪問頭信息// 例如: headers.getContentType(), headers.getAcceptLanguageAsLocales(), headers.getFirst("X-Custom-Header")long contentLength = headers.getContentLength();return "All headers (HttpHeaders object). Content-Length: " + contentLength + ". Headers: " + headers.toString();
}
  • 推薦使用 HttpHeaders 對象,因為它提供了類型安全的方法來訪問常見的頭,并且能正確處理多值頭和大小寫問題。

總結

  • @RequestHeader 用于將 HTTP 請求頭 的值綁定到方法參數。
  • 必須 使用 namevalue 屬性指定要讀取的頭名稱(除非特殊情況,但不推薦省略)。
  • 使用 required = false 使頭變為可選(不存在時為 nullOptional.empty())。
  • 使用 defaultValue = "value" 為可選頭提供默認值(頭不存在時生效,隱含 required=false)。
  • 可以將多值頭(逗號分隔)綁定到 List 或數組。
  • 可以通過將 @RequestHeader 應用于 Map, MultiValueMap 或(推薦的HttpHeaders 對象來訪問所有頭信息。
  • @RequestParam(用于查詢/表單參數)和 @PathVariable(用于路徑變量)不同,@RequestHeader 專注于 HTTP Headers。

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

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

相關文章

Rust 學習筆記:關于結構體的例題

Rust 學習筆記&#xff1a;關于結構體的例題 Rust 學習筆記&#xff1a;關于結構體的例題下面的程序能通過編譯嗎&#xff1f;下面的程序能通過編譯嗎&#xff1f;下面的程序能通過編譯嗎&#xff1f;哪種說法最能描述 Display 和 Debug 特質之間的區別&#xff1f;下面哪個選項…

STM32 SPI通信協議

1. SPI協議概述 1.1 什么是SPI&#xff1f; SPI&#xff08;Serial Peripheral Interface&#xff09;是由摩托羅拉公司于1980年代提出的同步串行通信協議&#xff0c;主要用于短距離高速芯片間通信。作為四線制全雙工通信協議&#xff0c;它以簡單的硬件實現和高效的傳輸速率…

92.一個簡單的輸入與顯示示例 Maui例子 C#例子

一、關于項目命名的注意事項 在開發.NET MAUI項目時&#xff0c;項目命名是一個不可忽視的細節。如果你習慣了在C#控制臺或WPF項目中使用中文項目名稱&#xff0c;那么在.NET MAUI中&#xff0c;你可能會遇到一些問題。我之前就因為使用中文項目名稱而導致項目無法直接運行&am…

Locate 3D:Meta出品自監督學習3D定位方法

標題&#xff1a; Locate 3D: Real-World Object Localization via Self-Supervised Learning in 3D 摘要&#xff1a; 我們提出了 Locate 3D&#xff0c;這是一種可根據指代表達&#xff08;如“沙發和燈之間的小咖啡桌”&#xff09;在三維場景中定位物體的模型。Locate 3…

FastAPI 與數據庫交互示例

目錄 安裝必要的包完整代碼示例運行應用使用說明API 端點說明代碼解析 下面將創建一個簡單的 FastAPI 應用程序&#xff0c;演示如何與 SQLite 數據庫進行交互。這個例子包括創建、讀取、更新和刪除&#xff08;CRUD&#xff09;操作。 安裝必要的包 首先&#xff0c;需要安裝…

YOLO旋轉目標檢測之ONNX模型推理

YOLO旋轉檢測相較于目標檢測而言&#xff0c;其只是最后的輸出層網絡發生了改變&#xff0c;一個最明顯的區別便是&#xff1a;目標檢測的檢測框是xywh&#xff0c;而旋轉檢測則為xywha&#xff0c;其中&#xff0c;這個a代表angle&#xff0c;即旋轉角度&#xff0c;其余的基本…

架構進階:深入學習企業總體架構規劃(Oracle 戰略專家培訓課件)【附全文閱讀】

本文主要討論了企業總體技術架構規劃的重要性與實施建議。針對Oracle戰略專家培訓課件中的內容&#xff0c;文章強調了行業面臨的挑戰及現狀分析、總體技術架構探討、SOA集成解決方案討論與問題解答等方面。文章指出&#xff0c;為了消除信息孤島、強化應用系統&#xff0c;需要…

llamafactory-cli webui啟動報錯TypeError: argument of type ‘bool‘ is not iterable

一、問題 在阿里云NoteBook上啟動llamafactory-cli webui報錯TypeError: argument of type ‘bool’ is not iterable This share link expires in 72 hours. For free permanent hosting and GPU upgrades, run gradio deploy from the terminal in the working directory t…

Gas 優化不足、升級機制缺陷問題

以下是針對智能合約中 Gas 優化不足 與 升級機制缺陷 的技術風險分析與解決方案: 一、Gas 優化不足 1. 核心問題 Gas 優化不足會導致合約執行成本過高,直接影響用戶體驗和協議可行性,尤其在交易高峰期可能引發鏈上擁堵或交易失敗。 2. 常見風險點 冗余計算與存儲操作 例如…

使用xlwings計算合并單元格的求和

有如下一個excel表 表內有合并單元格&#xff0c;現在需要求和&#xff0c;不能直接下拉填充公式怎么辦&#xff1f; 通常的辦法是先取消合并單元格&#xff0c;計算后&#xff0c;再次合并單元格&#xff0c;比較繁瑣。 在此&#xff0c;嘗試使用python和xlwings運行直接給出…

[創業之路-354]:農業文明到智能紀元:四次工業革命下的人類遷徙與價值重構

農業文明到智能紀元&#xff1a;四次工業革命下的人類遷徙與價值重構 從游牧到定居&#xff0c;從蒸汽轟鳴到算法洪流&#xff0c;人類文明的每一次跨越都伴隨著生產關系的劇烈震蕩。四次工業革命的浪潮不僅重塑了物質世界的生產方式&#xff0c;更將人類推向了身份認同與存在…

LeetCode 2302.統計得分小于 K 的子數組數目:滑動窗口(不需要前綴和)

【LetMeFly】2302.統計得分小于 K 的子數組數目&#xff1a;滑動窗口&#xff08;不需要前綴和&#xff09; 力扣題目鏈接&#xff1a;https://leetcode.cn/problems/count-subarrays-with-score-less-than-k/ 一個數組的 分數 定義為數組之和 乘以 數組的長度。 比方說&…

kafka學習筆記(四、生產者(客戶端)深入研究(二)——消費者協調器與_consumer_offsets剖析)

1.消費者協調器和組協調器 如果消費者客戶端中配置了多個分配策略&#xff0c;則多消費者的分區分配交由消費者協調器和組協調器來完成&#xff0c;他們之間使用一套組協調協議進行交互。 1.1.在均衡原理 將全部消費者分成多個子集&#xff0c;每個消費者組的子集在服務中對…

快速將FastAPI接口轉為模型上下文協議(MCP)!

fastapi_mcp 是一個用于將 FastAPI 端點暴露為模型上下文協議&#xff08;Model Context Protocol, MCP&#xff09;工具的庫&#xff0c;并且支持認證功能。 環境macbook&#xff0c;python3.13 pip install fastapi uvicorn fastapi-mcp 代碼 from fastapi import FastAPI, …

實驗數據的轉換

最近做實驗需要把x軸y軸z軸的數據處理一下&#xff0c;總結一下解決的方法&#xff1a; 源文件為兩個txt文檔&#xff0c;分別為x軸和y軸&#xff0c;如下&#xff1a; 最終需要達到的效果是如下&#xff1a; 就是需要把各個矩陣的數據整理好放在同一個txt文檔里。 步驟① …

第Y3周:yolov5s.yaml文件解讀

&#x1f368; 本文為&#x1f517;365天深度學習訓練營 中的學習記錄博客&#x1f356; 原作者&#xff1a;K同學啊 本次任務&#xff1a;將yolov5s網絡模型中的第4層的C3x2修改為C3x1&#xff0c;第6層的C3x3修改為C3x2。 首先輸出原來的網絡結構&#xff1a; from n pa…

Ansible安裝配置

一、前提 服務器操作系統均為centos7.9 主機ipmaster(Ansible管理端)172.25.192.2node1172.25.192.10node2172.25.192.3 更新/etc/hosts文件 二、安裝 master節點&#xff1a; 1. 安裝epel源 yum install -y epel-release 2. 安裝Ansible yum install -y ansible A…

MySQL中ROW_NUMBER() OVER的用法以及使用場景

使用語法 ROW_NUMBER() OVER ([PARTITION BY partition_column1, partition_column2, ...]ORDER BY sort_column1 [ASC|DESC], sort_column2 [ASC|DESC], ... )PARTITION BY&#xff1a;將數據按指定列分組&#xff0c;每組內單獨生成行號。ORDER BY&#xff1a;決定組內行號的…

【人工智能】釋放本地AI潛能:LM Studio用戶腳本自動化DeepSeek的實戰指南

《Python OpenCV從菜鳥到高手》帶你進入圖像處理與計算機視覺的大門! 解鎖Python編程的無限可能:《奇妙的Python》帶你漫游代碼世界 隨著大型語言模型(LLM)的快速發展,DeepSeek以其高效的性能和開源特性成為開發者關注的焦點。LM Studio作為一款強大的本地AI模型管理工具…

筆試強訓:Day3

一、牛牛沖鉆五&#xff08;模擬&#xff09; 登錄—專業IT筆試面試備考平臺_牛客網 #include<iostream> using namespace std; int main(){int t,n,k;string s;cin>>t;while(t--){cin>>n>>k>>s;int ret0;//統計加了多少星for(int i0;i<n;i)…