RequestHeader
本章紧接
@RequestParam,聚焦 HTTP 请求头(Request Header)的获取。如果说@RequestParam处理的是请求的"业务数据",那么@RequestHeader处理的就是请求的"元数据"——如客户端类型、认证令牌、内容格式等。这些信息不直接参与业务计算,却决定了请求如何被解析、如何被鉴权。
定义与作用
@RequestHeader 用于将 HTTP 请求头中的字段值绑定到 Controller 方法的参数上。
HTTP 请求头携带了关于请求本身的大量元信息:
- User-Agent:客户端是什么浏览器、什么操作系统
- Content-Type:请求体的数据格式(JSON、表单、XML)
- Authorization:认证令牌(Bearer Token、Basic Auth)
- Accept:客户端期望的响应格式
- X-Request-ID:链路追踪 ID
在 RESTful API 开发中,请求头常用于传递横切关注点的数据——这些数据与具体业务无关,但每个请求都可能需要(如鉴权、日志追踪、版本控制)。
生活类比:信封上的邮戳
想象飞翔科技收发室收到一封信件:
- 信纸内容(请求体):这是真正的业务数据,如"申请报销 500 元"
- 信封上的邮戳(请求头):包含发件地址、邮戳日期、特快标识等元信息
@RequestParam 读的是信纸上的具体内容(如报销金额),@RequestHeader 读的是信封上的邮戳(如发件人地址、邮件优先级)。两者各司其职,缺一不可。
核心原理
请求头绑定流程
与 @RequestParam 的核心区别:
| 维度 | @RequestParam | @RequestHeader |
|---|---|---|
| 数据来源 | request.getParameter() | request.getHeader() |
| 数据位置 | URL 查询参数 / 表单体 | HTTP 请求头 |
| 大小写敏感 | 参数名大小写不敏感 | 请求头名大小写不敏感(HTTP 规范) |
| 多值支持 | 同名参数多值 | 同名头字段多值(逗号分隔或重复出现) |
适用位置与常用属性
@RequestHeader 只能标注在 Controller 方法的参数 上。
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
name / value | String | "" | 请求头字段名,大小写不敏感 |
required | boolean | true | 是否必填 |
defaultValue | String | 无 | 缺失时的默认值 |
常见请求头对照表
| 请求头 | 典型值 | 使用场景 |
|---|---|---|
User-Agent | Mozilla/5.0 (Windows NT 10.0...) | 识别客户端类型、做兼容性适配 |
Content-Type | application/json | 告知服务器请求体格式 |
Accept | application/json | 告知服务器期望的响应格式 |
Authorization | Bearer eyJhbGciOiJIUzI1Ni... | JWT / OAuth2 令牌传递 |
X-Request-ID | 550e8400-e29b-41d4-a716-446655440000 | 分布式链路追踪 |
Host | api.feixiang.com | 虚拟主机、路由分发 |
Referer | https://feixiang.com/employees | 来源页面统计、防盗链 |
Cookie | sessionId=abc123; theme=dark | 会话状态(但获取 Cookie 推荐 @CookieValue) |
完整示例
场景
飞翔科技员工管理系统需要记录每个请求的客户端信息,用于安全审计和兼容性分析。架构师白歌要求后端小崔在接口中采集 User-Agent 和自定义的 X-Client-Version 头。
代码实现
package com.feixiang.web;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/employees")
public class EmployeeController {
/**
* 获取 User-Agent,识别客户端类型
*/
@GetMapping("/client-info")
public String getClientInfo(
@RequestHeader("User-Agent") String userAgent,
@RequestHeader(value = "X-Client-Version", required = false) String clientVersion) {
return String.format("客户端: %s, 版本: %s", userAgent, clientVersion);
}
/**
* 获取所有请求头(Map 形式)
*/
@GetMapping("/headers")
public String getAllHeaders(@RequestHeader Map<String, String> headers) {
return "请求头数量: " + headers.size() + ", Content-Type=" + headers.get("content-type");
}
/**
* 获取多值请求头(List 形式)
*/
@GetMapping("/multi-header")
public String getMultiValueHeader(@RequestHeader("Accept") List<String> acceptValues) {
return "Accept 头: " + acceptValues;
}
}
HTTP 请求示例
示例 1:获取 User-Agent
curl -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)" \
-H "X-Client-Version: 2.1.0" \
"http://localhost:8080/employees/client-info"
响应:
客户端: Mozilla/5.0 (Windows NT 10.0; Win64; x64), 版本: 2.1.0
示例 2:自定义头缺失(required=false)
curl -H "User-Agent: curl/7.68.0" \
"http://localhost:8080/employees/client-info"
响应:
客户端: curl/7.68.0, 版本: null
X-Client-Version 未传,由于 required=false,参数值为 null,不报错。
示例 3:获取所有请求头
curl -H "Content-Type: application/json" \
-H "X-Request-ID: 550e8400-e29b-41d4-a716" \
"http://localhost:8080/employees/headers"
响应:
请求头数量: 7, Content-Type=application/json
示例 4:多值 Accept 头
curl -H "Accept: application/json" \
-H "Accept: text/html" \
"http://localhost:8080/employees/multi-header"
响应:
Accept 头: [application/json, text/html]
易错场景与面试考点
误区一:请求头名大小写写错
现象:@RequestHeader("content-type") 和 @RequestHeader("Content-Type") 都能正常工作。
原理:HTTP/1.1 规范规定请求头字段名大小写不敏感。Spring MVC 底层调用 HttpServletRequest.getHeader(),该方法在标准实现中不区分大小写。
建议:虽然大小写不敏感,但团队应统一规范。推荐首字母大写的驼峰写法(Content-Type、User-Agent),与 RFC 规范一致。
误区二:用 @RequestHeader 获取 Cookie
现象:@RequestHeader("Cookie") String cookie 能拿到 sessionId=abc; theme=dark 这样的原始字符串。
问题:Cookie 字符串需要手动解析(按 ; 分割、URL 解码),繁琐且易错。
正确做法:使用专门的 @CookieValue 注解(下一节讲解),直接按 Cookie 名提取单个值:
@GetMapping("/session")
public String getSession(@CookieValue("sessionId") String sessionId) {
return "会话ID: " + sessionId;
}
误区三:请求头值包含中文未编码
现象:@RequestHeader("X-Employee-Name") String name 拿到乱码。
纠正:HTTP 请求头值默认按 ISO-8859-1 编码。如果需要在请求头中传递中文,客户端必须先进行 URL 编码(URLEncoder.encode("张三", "UTF-8")),服务端再 URL 解码。
最佳实践:业务数据(如员工姓名)不要放在请求头中传递,应放在请求体(@RequestBody)或查询参数(@RequestParam)中。
面试高频:@RequestHeader 和 @RequestParam 的区别
标准回答:
- 数据来源不同:
@RequestParam从 URL 查询参数或表单数据获取(getParameter()),@RequestHeader从 HTTP 请求头获取(getHeader()) - 用途不同:
@RequestParam用于业务数据(如搜索关键词、分页参数),@RequestHeader用于元数据(如认证令牌、客户端版本) - 大小写规则不同:请求参数名大小写不敏感(但通常按声明匹配),请求头名按 HTTP 规范大小写不敏感
- 多值处理:两者都支持多值,但请求头的多值通常以逗号分隔(如
Accept: application/json, text/xml),而参数多值通常重复出现(如id=1&id=2)
小结
@RequestHeader 是 Spring MVC 获取 HTTP 请求头元数据的核心注解。它将请求头字段映射为 Java 方法参数,支持必填控制、默认值和多值接收。
核心要点:
- 请求头名大小写不敏感,但团队应统一规范
- 业务数据不要放在请求头中传递,避免编码问题
- 获取 Cookie 应使用
@CookieValue,不要手动解析Cookie头 - 常用场景:鉴权令牌、客户端版本、链路追踪 ID
本章与全局的关系:本章讲解了"如何获取请求的元数据"。下一节 @CookieValue 将专门讲解 HTTP Cookie 的获取方式,它是请求头机制的一个特例,但拥有更便捷的专用注解。