Spring 中的 @RequestHeader 和 @CookieValue 注解的作用是什么?
- 标签:后端、Spring
🏛 业务架构师
这两个注解处理的是 HTTP 请求"头部位"的数据绑定:
- @RequestHeader:把请求头字段绑定到参数——
@RequestHeader("X-Tenant-Id") String tenantId。业务高频用途:租户标识、链路 traceId、灰度标、渠道号、token这类网关/调用方注入的元数据。支持required=false+ 默认值; - @CookieValue:把指定 Cookie 绑定到参数——传统会话场景取
JSESSIONID/ 登录态 Cookie。
架构师视角,我的实战观点是**"哪些信息该走请求头"是 API 治理的一部分**:
- 身份与上下文走 Header,业务数据走 Body——网关统一鉴权后把
X-User-Id、X-Tenant-Id、traceId 注入 Header 下传,下游服务从 Header 恢复上下文,业务代码零鉴权逻辑,这是标准的多层架构分工; - Cookie 在微服务体系里已边缘化:无状态服务 + JWT/网关鉴权成为主流,Cookie 主要残留在面向浏览器的 BFF 层。服务间调用读 Header 而不是 Cookie——Cookie 是浏览器概念,内网 RPC 传它属于概念错位;
- 安全提醒:从 Header/Cookie 来的值都是不可信输入(可被客户端伪造),网关覆写鉴权头、服务侧校验签名是底线,不能拿 Header 里的 userId 直接当身份信任。
一句话:小注解,大分工——它们承载的是"上下文传递协议"的设计。
🏗 系统架构师
作用:把请求头/Cookie 绑定到方法参数,支持必填与缺省值(required、defaultValue)。
架构视角:它们是「元数据通道」的接入点——HTTP 头承载请求上下文而非业务载荷:Authorization、X-Trace-Id、X-Tenant-Id、X-Forwarded-For。我把「业务语义进 body、上下文语义进 header」当 API 设计纪律,两边职责不混。
生产注意:
- 头大小限制:Tomcat 默认整个 header 区 8KB,自定义头要克制,别把业务数据塞头里;
- 网关侧头清洗:外部可伪造的头(X-User-Id 这类)必须在网关剥掉重写,下游只信任网关注入的身份——南北向流量的安全铁律;
- Cookie 注意 HttpOnly/Secure/SameSite 属性与 CSRF 策略;跨域时 Allow-Credentials 必须配具体域名而非通配;
- traceId 从头进来后第一时间进 MDC,日志与链路才能串起来。
💻 全栈开发专家
分别从请求头和 Cookie 取值注入参数:
java
@GetMapping("/tenant")
public String tenant(@RequestHeader("X-Tenant-Id") Long tenantId,
@RequestHeader(value = "X-Trace-Id", required = false) String traceId,
@CookieValue(value = "SESSION", required = false) String session) {
...
}要点:
required默认 true,缺失抛MissingRequestHeaderException返回 400;可选头配required=false+defaultValue- 全量收:
@RequestHeader HttpHeaders headers(多值友好) - 常见用途:网关注入的
X-Trace-Id、灰度标记、租户头;Cookie 取会话或 A/B 标记 - 安全提示(我参与安全评审的固定检查项):只有网关清洗过的头才可信——服务直接暴露时客户端可伪造任意头,鉴权信息必须以网关透传的为准
- 排查取不到值:curl -v 对比请求头、检查网关是否透传(Nginx 要
proxy_set_header显式传)
配套认知:也可以从 RequestContextHolder 拿原始 request,但注解方式参数显式、单测直接传参 mock,可测性更好。