Skip to content

Spring 中的 @RequestHeader 和 @CookieValue 注解的作用是什么? ​

  • 标签:后端、Spring

🏛 业务架构师 ​

这两个注解处理的是 HTTP 请求"头部位"的数据绑定:

  • @RequestHeader:把请求头字段绑定到参数——@RequestHeader("X-Tenant-Id") String tenantId。业务高频用途:租户标识、链路 traceId、灰度标、渠道号、token这类网关/调用方注入的元数据。支持 required=false + 默认值;
  • @CookieValue:把指定 Cookie 绑定到参数——传统会话场景取 JSESSIONID / 登录态 Cookie。

架构师视角,我的实战观点是**"哪些信息该走请求头"是 API 治理的一部分**:

  1. 身份与上下文走 Header,业务数据走 Body——网关统一鉴权后把 X-User-Id、X-Tenant-Id、traceId 注入 Header 下传,下游服务从 Header 恢复上下文,业务代码零鉴权逻辑,这是标准的多层架构分工;
  2. Cookie 在微服务体系里已边缘化:无状态服务 + JWT/网关鉴权成为主流,Cookie 主要残留在面向浏览器的 BFF 层。服务间调用读 Header 而不是 Cookie——Cookie 是浏览器概念,内网 RPC 传它属于概念错位;
  3. 安全提醒:从 Header/Cookie 来的值都是不可信输入(可被客户端伪造),网关覆写鉴权头、服务侧校验签名是底线,不能拿 Header 里的 userId 直接当身份信任。

一句话:小注解,大分工——它们承载的是"上下文传递协议"的设计。

🏗 系统架构师 ​

作用:把请求头/Cookie 绑定到方法参数,支持必填与缺省值(required、defaultValue)。

架构视角:它们是「元数据通道」的接入点——HTTP 头承载请求上下文而非业务载荷:Authorization、X-Trace-Id、X-Tenant-Id、X-Forwarded-For。我把「业务语义进 body、上下文语义进 header」当 API 设计纪律,两边职责不混。

生产注意:

  1. 头大小限制:Tomcat 默认整个 header 区 8KB,自定义头要克制,别把业务数据塞头里;
  2. 网关侧头清洗:外部可伪造的头(X-User-Id 这类)必须在网关剥掉重写,下游只信任网关注入的身份——南北向流量的安全铁律;
  3. Cookie 注意 HttpOnly/Secure/SameSite 属性与 CSRF 策略;跨域时 Allow-Credentials 必须配具体域名而非通配;
  4. 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,可测性更好。