CookieValue
本章紧接
@RequestHeader,专门讲解 HTTP Cookie 的获取机制。Cookie 本质上是请求头中的一个字段(Cookie: name=value; name2=value2),但由于其使用频率极高、格式特殊(分号分隔的多键值对),Spring MVC 提供了独立的@CookieValue注解,让开发者无需手动解析原始 Cookie 字符串,直接按 Cookie 名提取值。
定义与作用
@CookieValue 用于将 HTTP 请求中指定名称的 Cookie 值绑定到 Controller 方法的参数上。
HTTP 请求中的 Cookie 以如下格式出现在请求头中:
Cookie: sessionId=abc123; userPref=dark; lastVisit=2024-01-15
如果直接用 @RequestHeader("Cookie") 获取,得到的是一整条未解析的字符串,需要手动按 ; 分割、按 = 提取、做 URL 解码。@CookieValue 把这个繁琐过程封装起来,让开发者像使用 @RequestParam 一样简单地获取单个 Cookie。
生活类比:储物柜取物
想象飞翔科技大楼的储物柜区:
- @RequestHeader("Cookie"):给你一张整柜区的清单照片,你自己找柜子号、自己开锁、自己取物
- @CookieValue("sessionId"):你报出柜子号
sessionId,管理员直接把里面的东西递给你
@CookieValue 就是那位"管理员"——你只需告诉它 Cookie 的名字,它负责从整串 Cookie 中定位、提取、解码。
核心原理
Cookie 获取流程
与 @RequestHeader 获取 Cookie 的对比:
| 维度 | @RequestHeader("Cookie") | @CookieValue("name") |
|---|---|---|
| 获取方式 | 原始字符串 | 单个已解析的值 |
| 解析工作 | 开发者手动分割、解码 | Spring 自动完成 |
| 代码可读性 | 低(需要解析逻辑) | 高(声明式获取) |
| 空值处理 | 需判断字符串是否包含目标 Cookie | required=false 直接为 null |
| 适用场景 | 需要遍历所有 Cookie 的罕见场景 | 获取已知名称的单个 Cookie |
适用位置与常用属性
@CookieValue 只能标注在 Controller 方法的参数 上。
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
name / value | String | "" | Cookie 的名称(键) |
required | boolean | true | Cookie 是否必须存在 |
defaultValue | String | 无 | Cookie 缺失时的默认值 |
完整示例
场景
飞翔科技员工管理系统使用 Cookie 保存用户主题偏好(theme)和会话 ID(sessionId)。前端黄俪在登录后将这些 Cookie 写入浏览器,后续请求自动携带。后端小崔需要读取这些 Cookie 来个性化响应。
代码实现
package com.feixiang.web;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/employees")
public class EmployeeController {
/**
* 读取会话 Cookie(必填)
*/
@GetMapping("/profile")
public String getProfile(@CookieValue("sessionId") String sessionId) {
return "当前会话: " + sessionId;
}
/**
* 读取主题偏好(可选,默认 light)
*/
@GetMapping("/theme")
public String getTheme(
@CookieValue(value = "theme", required = false, defaultValue = "light") String theme) {
return "当前主题: " + theme;
}
/**
* 同时读取多个 Cookie
*/
@GetMapping("/preferences")
public String getPreferences(
@CookieValue("sessionId") String sessionId,
@CookieValue(value = "theme", required = false, defaultValue = "light") String theme,
@CookieValue(value = "lang", required = false, defaultValue = "zh-CN") String lang) {
return String.format("会话=%s, 主题=%s, 语言=%s", sessionId, theme, lang);
}
}
HTTP 请求示例
示例 1:读取单个必填 Cookie
curl -b "sessionId=abc123def456" \
"http://localhost:8080/employees/profile"
响应:
当前会话: abc123def456
示例 2:Cookie 缺失(required=true,报错)
curl "http://localhost:8080/employees/profile"
响应(HTTP 400):
{
"timestamp": "2024-01-15T10:05:12.456+00:00",
"status": 400,
"error": "Bad Request",
"message": "Required cookie 'sessionId' for method parameter type String is not present"
}
示例 3:可选 Cookie + 默认值
curl -b "sessionId=abc123" \
"http://localhost:8080/employees/theme"
响应:
当前主题: light
theme Cookie 未携带,使用默认值 light。
示例 4:多 Cookie 同时读取
curl -b "sessionId=abc123; theme=dark; lang=en-US" \
"http://localhost:8080/employees/preferences"
响应:
会话=abc123, 主题=dark, 语言=en-US
易错场景与面试考点
误区一:Cookie 值包含特殊字符未编码
现象:Cookie 中存储中文用户名 @CookieValue("userName") String name 拿到乱码。
原理:Cookie 值在传输过程中按 RFC 6265 规范进行编码。如果客户端写入时未做 URLEncoder.encode(),服务端读取时就会乱码。
解决:
- 客户端写入:
Cookie cookie = new Cookie("userName", URLEncoder.encode("张三", "UTF-8")); - 服务端读取后手动解码:
URLDecoder.decode(name, "UTF-8")
最佳实践:不要在 Cookie 中存储复杂业务数据。Cookie 适合存会话标识、简单偏好设置。用户姓名等数据应存服务端 Session 或数据库。
误区二:混淆 Cookie 的 name 和 value
错误代码:
@GetMapping("/test")
public String test(@CookieValue("abc123") String sessionId) {
// 错误!"abc123" 是 Cookie 的值,不是名字
}
纠正:@CookieValue 的参数是 Cookie 的名称(name),不是值。正确的写法:
@CookieValue("sessionId") String sessionId // 找 name="sessionId" 的 Cookie
误区三:试图用 @CookieValue 设置 Cookie
错误认知:"@CookieValue 可以读写 Cookie"
纠正:@CookieValue 是只读注解,只能获取请求中携带的 Cookie。要设置响应 Cookie,需要使用 HttpServletResponse:
@GetMapping("/set-cookie")
public String setCookie(HttpServletResponse response) {
Cookie cookie = new Cookie("theme", "dark");
cookie.setMaxAge(7 * 24 * 60 * 60); // 7天
cookie.setPath("/");
response.addCookie(cookie);
return "Cookie 已设置";
}
面试高频:获取 Cookie 有几种方式?
标准回答:
@CookieValue(推荐):声明式获取单个 Cookie,简洁、类型安全@RequestHeader("Cookie"):获取原始 Cookie 字符串,需手动解析,适合需要遍历所有 Cookie 的场景HttpServletRequest.getCookies():传统 Servlet 方式,返回Cookie[]数组,需手动遍历匹配
在 Spring MVC 项目中,优先使用 @CookieValue,它是专门为 Cookie 场景设计的注解,语义清晰,代码简洁。
小结
@CookieValue 是 Spring MVC 获取 HTTP Cookie 的专用注解。它将客户端请求中携带的 Cookie 按名称提取,自动完成解析和解码,让开发者无需处理原始 Cookie 字符串的分割逻辑。
核心要点:
@CookieValue只读,不能用于设置 Cookie- 属性与
@RequestParam一致:name、required、defaultValue - Cookie 值可能包含编码问题,中文需 URL 编解码
- 复杂业务数据不要存 Cookie,应存服务端 Session
本章与全局的关系:本章讲解了"如何获取客户端状态 Cookie"。下一节 @RequestBody 将进入请求体数据的解析,讲解 JSON/XML 等结构化数据如何反序列化为 Java 对象——这是 RESTful API 开发的核心技能。