前言
在 spring boot 开发中,http 请求头(header)是客户端和服务器之间传递元数据的重要方式。通过请求头,客户端可以传递认证信息、内容类型、语言偏好等数据。spring boot 提供了 @requestheader 注解,用于方便地从 http 请求头中提取数据。本文将详细介绍 @requestheader 注解的使用方法,包括基本用法、默认值处理、多值头处理以及实际应用场景。
一、注解定义与核心属性
1.1 @requestheader 是什么
在构建现代 web 应用或 restful api 时,我们经常需要从 http 请求中提取元数据信息。其中,请求头(request headers) 是传递客户端身份、认证令牌、内容类型、语言偏好等关键信息的重要载体。@requestheader 是 spring framework 提供的一个方法参数注解,用于将 http 请求头中的特定字段值自动绑定到控制器方法的参数上。它属于 spring mvc 的数据绑定机制的一部分,与 @requestparam、@pathvariable、@requestbody 等注解共同构成 spring 对 http 请求的结构化解析能力。
⚠️注意:@requestheader 仅在 spring mvc 的控制器方法(@controller、@restcontroller)中有效,在 service、util 或普通 bean 方法中使用将被忽略。
1.2 源码定义
@requestheader 注解的实现基于spring mvc的参数绑定机制,它通过 @target 和 @retention 注解指定其作用于方法参数级别,并在运行时通过 spring 的内部机制将请求头的值注入到相应的参数上。
@target({elementtype.parameter})
@retention(retentionpolicy.runtime)
@documented
public @interface requestheader {
@aliasfor("name")
string value() default "";
@aliasfor("value")
string name() default "";
boolean required() default true;
string defaultvalue() default valueconstants.default_none;
}| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| value | string | 指定要绑定的请求头的名称 | |
| name | string | ||
| required | boolean | true | 是否必须提供该请求头,如果为 true 且请求头不存在,则会抛出 400 异常。 如果设置为false时,当请求中没有此参数,将会默认为 null。 而对于基本数据类型的变量,则必须有值,这时会抛出空指针异常。 如果允许空值,则接口中变量需要使用包装类来声明。 |
| defaultvalue | string | valueconstants.default_none | 当请求头不存在时的默认值,仅在 required = false 时生效 |
需要注意的是,value() 和 name() 是别名关系,二者等价,通常使用 value。如果方法参数的名称与请求头名称相同,那么可以省略 value 元素。然而,需要注意的是,某些请求头名称(如user-agent)并不是有效的java变量名,因此在这种情况下,我们不能省略value元素。
二、工作原理与请求处理流程
2.1 请求头处理流程

2.2 核心处理阶段
参数解析器选择:requestheadermethodargumentresolver 处理带有 @requestheader 的参数
请求头获取:从 httpservletrequest 获取指定请求头值
类型转换:使用 conversionservice 转换为目标类型
public class defaultformattingconversionservice implements conversionservice { public <t> t convert(@nullable object source, class<t> targettype) { // 查找合适的转换器 genericconverter converter = getconverter(sourcetype, targettype); return (t) converter.convert(source, sourcetype, targettype); } }默认值处理:当请求头缺失且存在默认值时应用
@override protected object resolveargument(methodparameter parameter, modelandviewcontainer mavcontainer, nativewebrequest webrequest, webdatabinderfactory binderfactory) throws exception { object arg = super.resolveargument(parameter, mavcontainer, webrequest, binderfactory); // 处理默认值 if (arg == null && !valueconstants.default_none.equals(namedvalueinfo.defaultvalue())) { arg = resolvedefaultvalue(namedvalueinfo.defaultvalue()); } return arg; }必填校验:检查必需请求头是否存在
三、使用场景与最佳实践
3.1 基本用法
如果只需要获取某个特定的请求头,可以使用 @requestheader 注解并指定 header 名称。假设我们需要根据用户的 accept-language 请求头来返回不同语言的响应,使用 @requestheader 可以轻松实现:
@getmapping("/locale")
public string getprofile(@requestheader("accept-language") string language) {
// 根据locale返回不同语言的响应
return "response in " + language;
}⚠️注意:如果请求中没有 accept-language 这个 header,默认会返回 400 错误。
如上这段代码用于根据客户端的 accept-language 请求头返回相应语言的响应,其功能是根据客户端的 http 请求头 accept-language 来返回不同语言的响应。使用这种方式代码简洁、语义清晰,无需注入 httpservletrequest,自动完成字符串转换(支持基本类型、枚举等)。在某些情况下,可能会过度依赖spring框架的注解,导致代码难以移植。
3.2 可选参数与默认值
默认情况下,header 是必须的。如果请求中没有该 header,将抛出异常并返回 400。如果希望在请求头缺失时不出现异常,可以将 required 设置为 false,此时需要手动判断。或者设置 header 默认值,required 会自动设置为 false,这样即使请求中没有该 header,也会使用默认值,避免 null 判断。
@postmapping("/submit")
public responseentity<?> submit(
@requestheader(value = "x-request-id", required = false) string requestid,
@requestheader(value = "user-agent", defaultvalue = "unknown") string useragent) {
if(traceid == null){
// 自动生成
traceid = generatetraceid();
}
return appinfo(traceid, useragent);
}defaultvalue 仅在 required = false 且请求头缺失时生效,若同时设置 required = true 和 defaultvalue,defaultvalue 不会被使用(因为 spring 认为该头必须存在)。
3.3 获取所有 headers
@requestheader 可以获取单个请求头的值,也可以获取所有请求头,并将其作为 multivaluemap 或 map 类型传递给方法参数。如果不确定请求中会包含哪些 headers,或者不希望方法参数列表太长,可以使用 @requestheader 不指定名称,直接获取所有 headers,可以选择使用以下几种类型接收:
使用 map 接收所有请求头,只获取每个 header 的第一个值。
@getmapping("/analytics") public map<string, string> analyzeheaders(@requestheader map<string, string> headers) { // headers 包含所有请求头(key 不区分大小写,统一转为小写。注意:实际保留原始大小写) return headers; }使用 multivaluemap 接收请求头,可以获取多个值。
@requestmapping("/listheaders") public map<string, object> listheaders(@requestheader multivaluemap<string, string> headers) { map<string, object> result = new hashmap<>(); headers.foreach((key, value) -> { // 日志中输出所有请求头 system.out.println(string.format("header '%s' = %s", key, value)); }); result.put("code", 0); result.put("msg", "success"); result.put("headers", headers); return result; }使用 httpheaders 接收请求头,这是spring提供的一个专门用于处理请求头的类,它实现了 multivaluemap<string, string> 接口,主要用于获取标准 header。
@requestmapping("/getallhttpheaders") public map<string, object> getallhttpheaders(@requestheader httpheaders headers) { headers.foreach((key, value) -> { // 日志中输出所有请求头 system.out.println(string.format("getallhttpheaders '%s' = %s", key, value)); }); map<string, object> result = new hashmap<>(); result.put("code", 0); result.put("msg", "success"); result.put("headers", headers); return result; }
⚠️ 注意:如果指定的 header 不存在,从 map、multivaluemap 或 httpheaders 获取时会返回 null。
3.4 处理多值请求头
某些请求头可能包含多个值(如 accept 头),可以使用 list<string> 或 multivaluemap<string, string> 来提取。
import java.util.list;
@getmapping("/accept-header")
public string getacceptheader(@requestheader("accept") list<string> acceptheaders) {
return "accept headers: " + acceptheaders.tostring();
}四、最佳实践总结
4.1 请求头使用规范
| 请求头 | 典型用途 | 示例 |
|---|---|---|
| authorization | 身份认证 | bearer令牌 |
| accept | 内容协商 | application/json |
| content-type | 请求体类型 | application/json |
| user-agent | 客户端识别 | 浏览器信息 |
| x-request-id | 请求追踪 | uuid |
| if-modified-since | 缓存控制 | http日期格式 |
| accept-language | 语言选择 | en-us |
| api-version | 版本控制 | v2 |
4.2 与 httpservletrequest.getheader() 的对比
| 特性 | @requestheader | request.getheader() |
|---|---|---|
| 代码位置 | controller 方法参数 | 任意有 request 的地方 |
| 类型安全 | ✅ 支持自动转换 | ❌ 仅返回 string |
| 可读性 | ✅ 声明式,意图明确 | ❌ 命令式,需查找 key |
| 校验能力 | ✅ 内置 required/default | ❌ 需手动判空 |
| 测试友好性 | ✅ 易于 mock 参数 | ❌ 需 mock httpservletrequest |
| 耦合度 | 低(无 servlet api 依赖) | 高(强依赖 servlet api) |
五、总结
在现代web应用程序中,安全性是一个至关重要的方面,特别是当我们处理敏感数据或执行受限操作时。@requestheader 注解在这方面发挥了重要作用,它允许开发者轻松地从http请求头中提取信息,例如认证令牌,并据此进行安全决策。通过这种方式,我们能够精确控制对受限端点的访问,仅允许通过身份验证的用户访问敏感数据。这不仅增强了应用程序的安全性,还提供了一种灵活的方法来处理各种基于请求头的逻辑。
然而,合理使用这一工具的同时,开发者也需要关注安全性的其它方面,比如确保敏感信息的加密存储、使用https来保护数据传输的安全等。此外,实现鲁棒的身份验证逻辑和错误处理机制也是至关重要的,以确保应用程序能够妥善处理无效或恶意的请求。
到此这篇关于spring注解秘籍之如何优雅地使用@requestheader的文章就介绍到这了,更多相关spring注解@requestheader内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论