乐途乐途
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
  • 学习路径
  • 第1章 SpringMVC概述与DispatcherServlet

    • 本章导读:Spring MVC概述与DispatcherServlet
    • Spring MVC 是什么
    • MVC 设计模式
    • 前端控制器模式
    • DispatcherServlet
    • 核心组件协作
  • 第2章 控制器与请求映射

    • 本章导读:控制器与请求映射
    • Controller
    • RestController
    • RequestMapping
    • GetMapping
    • PostMapping
    • PutMapping
    • DeleteMapping
    • PathVariable
    • RESTful
    • 请求映射原理
  • 第3章 请求参数获取与转换

    • 本章导读:请求参数获取与转换
    • RequestParam
    • RequestBody
    • RequestHeader
    • CookieValue
    • Model
    • ModelAttribute
    • 数据绑定原理
    • 数据校验
  • 第4章 响应数据与视图解析

    • 本章导读:响应数据与视图解析
    • ResponseBody
    • ResponseEntity
    • ModelAndView
    • ViewResolver
    • HttpMessageConverter
    • forward与redirect
  • 第5章 拦截器过滤器与跨域

    • 本章导读:拦截器、过滤器与跨域
    • HandlerInterceptor
    • WebMvcConfigurer
    • CrossOrigin
    • 登录验证实战
  • 第6章 文件上传与异常处理

    • 本章导读:文件上传与异常处理
    • MultipartFile
    • 文件下载
    • ExceptionHandler
    • ControllerAdvice
    • RestControllerAdvice
    • ResponseStatus
  • 第7章 高级特性与最佳实践

    • 本章导读:高级特性与最佳实践
    • SessionAttributes
    • SessionAttribute
    • RedirectAttributes
    • MockMvc测试
    • 国际化
    • 最佳实践
  • 第8章 扩展与异步机制

    • 本章导读:扩展与异步机制
    • 异步请求处理
    • 自定义参数解析器
    • 内容协商

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 自动完成
代码可读性低(需要解析逻辑)高(声明式获取)
空值处理需判断字符串是否包含目标 Cookierequired=false 直接为 null
适用场景需要遍历所有 Cookie 的罕见场景获取已知名称的单个 Cookie

适用位置与常用属性

@CookieValue 只能标注在 Controller 方法的参数 上。

属性类型默认值说明
name / valueString""Cookie 的名称(键)
requiredbooleantrueCookie 是否必须存在
defaultValueString无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 有几种方式?

标准回答:

  1. @CookieValue(推荐):声明式获取单个 Cookie,简洁、类型安全
  2. @RequestHeader("Cookie"):获取原始 Cookie 字符串,需手动解析,适合需要遍历所有 Cookie 的场景
  3. 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 开发的核心技能。

上一页
RequestHeader
下一页
Model