Cookie 是什么?
要明白 Cookie 不是 Java 语言独有的特性,而是 HTTP 协议的一部分,它是一种由服务器发送到用户浏览器并保存在本地的小型文本文件。

当用户再次访问同一个网站时,浏览器会自动将之前保存的 Cookie 发送给服务器,这样,服务器就能识别出这个用户,并“之前的一些状态信息。
在 Java Web 开发中,我们主要通过 Servlet 和 JSP 技术来创建、读取和操作 Cookie。
Cookie 的主要作用
Cookie 在 Web 应用中扮演着至关重要的角色,其核心作用可以概括为以下几点:
会话管理 - 最核心的用途
这是 Cookie 最经典和广泛的应用,在 HTTP 协议中,本身是无状态的,这意味着服务器无法区分两个连续的请求是否来自同一个用户,Cookie 通过为每个用户分配一个唯一的标识符(如 JSESSIONID),解决了这个问题。

-
工作原理:
- 用户第一次访问一个支持会话的网站(如购物网站)。
- 服务器创建一个会话对象,并生成一个唯一的会话 ID(
A1B2C3D4E5F6)。 - 服务器将这个会话 ID 以 Cookie 的形式(通常名为
JSESSIONID)发送给浏览器。 - 浏览器收到后,将此 Cookie 保存在本地。
- 当用户在该网站的其他页面进行跳转或刷新时,浏览器会自动带上这个
JSESSIONID。 - 服务器通过读取 Cookie 中的
JSESSIONID,就能找到之前为该用户创建的会话对象,从而获取用户的购物车信息、登录状态等。
-
例子:
- 购物车:你将商品加入购物车,服务器将购物车内容与你的会话 ID 关联,即使你刷新了页面或点击了其他商品,服务器也能通过会话 ID 找到你的购物车。
- 用户登录状态:你登录成功后,服务器会在你的会话中标记“已登录”,只要会话有效,你在网站的任何操作都会被视为已登录用户。
个性化设置
网站可以根据用户的偏好来定制其浏览体验,这些偏好信息就存储在 Cookie 中。
-
工作原理:
(图片来源网络,侵删)- 用户在网站上进行个性化设置,例如选择语言(中文/英文)、主题(深色/浅色模式)、页面布局等。
- 服务器将用户的这些选择以 Cookie 的形式发送给浏览器。
- 下次用户访问时,浏览器会自动发送这些 Cookie,服务器根据这些信息为用户提供定制化的页面。
-
例子:
- 记住语言偏好:你访问一个新闻网站,选择了“中文”语言,网站会将
language=zh-CN写入 Cookie,下次你再访问时,页面会自动显示中文内容。 - 记住用户名:登录页面有一个“记住用户名”的选项,勾选后,服务器会将你的用户名保存在 Cookie 中,下次访问时,登录框会自动填充你的用户名。
- 记住语言偏好:你访问一个新闻网站,选择了“中文”语言,网站会将
跟踪与分析
网站管理员使用 Cookie 来收集用户行为数据,以分析网站流量、用户习惯和优化网站设计。
-
工作原理:
- 网站嵌入一个第三方分析服务(如 Google Analytics)的脚本。
- 该脚本会设置一个或多个 Cookie,用于记录你的访问来源、访问的页面、停留时间等信息。
- 这些 Cookie 在你访问该网站的多个页面时被不断更新,最终被发送到分析服务器。
-
例子:
- 网站流量统计:分析工具通过 Cookie 识别“独立访客”,并统计他们浏览了哪些页面,形成了网站的热力图和用户行为路径。
- 广告追踪:广告网络使用 Cookie 来记录你访问过的网站,以便向你展示相关的广告(即“行为广告”)。
在 Java (Servlet/JSP) 中如何操作 Cookie?
下面是一个简单的示例,展示如何在 Java Web 应用中创建和读取 Cookie。
创建和发送 Cookie (在 Servlet 中)
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/createCookie")
public class CreateCookieServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 创建一个 Cookie 对象
// 参数: cookie的名称, cookie的值
Cookie userCookie = new Cookie("username", "john_doe");
Cookie themeCookie = new Cookie("theme", "dark");
// 2. 可选: 设置 Cookie 的属性
// 设置 Cookie 的有效期 (单位: 秒)
// 如果不设置,Cookie 会在浏览器关闭时被删除(会话 Cookie)
userCookie.setMaxAge(60 * 60 * 24); // 有效期为1天 (24小时)
themeCookie.setMaxAge(60 * 60 * 24);
// 设置 Cookie 的路径,表示该 Cookie 在哪个路径下有效
// "/" 表示在整个网站下都有效
userCookie.setPath("/");
themeCookie.setPath("/");
// 3. 将 Cookie 添加到响应中
// 这会将 "Set-Cookie" 头部信息添加到 HTTP 响应中
response.addCookie(userCookie);
response.addCookie(themeCookie);
// 发送一个响应给客户端
response.setContentType("text/html");
response.getWriter().println("<h1>Cookies have been set!</h1>");
response.getWriter().println("<p>Check your browser's developer tools (Application/Storage -> Cookies) to see them.</p>");
}
}
读取 Cookie (在 Servlet 或 JSP 中)
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/readCookie")
public class ReadCookieServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 从请求中获取所有的 Cookie
Cookie[] cookies = request.getCookies();
response.setContentType("text/html");
response.getWriter().println("<h1>Reading Cookies:</h1>");
// 2. 遍历 Cookie 数组
if (cookies != null) {
for (Cookie cookie : cookies) {
// 3. 获取 Cookie 的名称和值
String name = cookie.getName();
String value = cookie.getValue();
response.getWriter().println("<p>Cookie Name: " + name + ", Value: " + value + "</p>");
}
} else {
response.getWriter().println("<p>No cookies found.</p>");
}
}
}
Cookie 的优缺点与替代方案
优点
- 简单易用:API 简单,在所有浏览器中得到广泛支持。
- 服务器负载小:数据存储在客户端,服务器不需要查询数据库或会话存储来获取信息。
- 可配置性强:可以设置路径、域名、有效期等属性,非常灵活。
缺点
- 安全性较低:
- 明文传输:Cookie 在 HTTP 中是明文传输的,容易被窃听(除非使用 HTTPS)。
- 易被篡改:用户可以手动修改或删除自己电脑上的 Cookie。
- 敏感信息风险:不应将密码、信用卡号等敏感信息存入 Cookie。
- 大小和数量限制:
- 每个 Cookie 的大小通常限制在 4KB 左右。
- 每个域名下的 Cookie 数量通常限制在 50个 左右。
- 用户可以禁用:出于隐私考虑,用户可以在浏览器设置中禁用 Cookie,导致依赖 Cookie 的功能失效。
替代方案
-
Session (会话):
- 机制:Session 数据存储在服务器端,客户端只保存一个 Session ID(通常通过 Cookie 传递)。
- 优点:安全性高,可以存储任意类型和大小的对象。
- 缺点:占用服务器内存资源,在分布式系统中需要额外的机制(如 Redis)来共享 Session。
-
LocalStorage 和 SessionStorage (Web 存储):
- 机制:HTML5 提供的客户端存储方案,数据存储在浏览器中,不参与 HTTP 请求。
- LocalStorage:永久存储,除非手动清除。
- SessionStorage:会话级别存储,浏览器关闭后数据被清除。
- 优点:存储容量更大(5MB+),不随 HTTP 请求自动发送,减少了网络流量。
- 缺点:API 只能存字符串,安全性同样不高,且兼容性略低于 Cookie。
-
Token (如 JWT - JSON Web Token):
- 机制:一种无状态的身份验证方案,用户登录后,服务器生成一个加密的 Token 返回给客户端,客户端后续请求在 Header 中携带此 Token,服务器验证 Token 的合法性即可。
- 优点:无状态,适合分布式系统,安全性高(可结合 HTTPS 和签名),不依赖 Cookie。
- 缺点:Token 本身较大,每次请求都需传递,增加了网络开销。
| 特性 | 描述 |
|---|---|
| 本质 | HTTP 协议的一部分,是存储在客户端的文本文件。 |
| 核心作用 | 会话管理(如购物车、登录状态)、个性化设置(如语言、主题)、用户跟踪(如网站分析)。 |
| Java 实现 | 在 Servlet 中通过 request.getCookies() 读取,通过 response.addCookie() 发送。 |
| 优点 | 简单、通用、减轻服务器负载。 |
| 缺点 | 安全性低、有大小和数量限制、可被用户禁用。 |
| 现代应用 | 在小型应用和简单状态管理中依然常用,在大型、安全要求高的系统中,常与 Session 或 JWT Token 结合使用。 |
Cookie 是 Web 开发中一个基础而强大的工具,它弥补了 HTTP 协议无状态的缺陷,是实现个性化用户体验和状态持久化的基石,理解其工作原理和优缺点,对于构建健壮的 Web 应用至关重要。
