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.mzph.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)…