Cookie对象
在 Servlet 中,Cookie 是用于在客户端(浏览器)存储少量数据的一种机制,常用于会话管理、用户偏好设置等场景
(会话管理用于跟踪用户在网站中的状态(如登录状态、购物车内容)。)
(用户偏好设置存储用户的个性化配置(如语言、主题颜色、时区))
Crtl +左键 可以查看源码
Cookie的创建与发送
创建
- 服务器创建 Cookie:Servlet 通过
response.addCookie()
向客户端发送 Cookie。
Cookie cookie = new Cookie("name", "admin");
resp.addCookie(cookie);
- 浏览器在向服务器发送请求时,会自动检查当前域名和路径下的 Cookie。
- 如果存在符合条件的 Cookie(未过期、路径匹配、域名匹配等),浏览器会将这些 Cookie 添加到请求头的
Cookie
字段中
例如:
GET /your-servlet-path HTTP/1.1
Cookie: name=admin; sessionId=abc123
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 创建 Cookie 对象
Cookie cookie = new Cookie("name", "admin");
// 将 Cookie 添加到响应
resp.addCookie(cookie);
}
接受
- 客户端存储 Cookie:浏览器保存 Cookie(键值对),并在后续请求中自动携带(通过
request.getCookies()
读取)[就算服务器关了,只要没有失效,cookie会一直存在浏览器]
GET /your-servlet-path HTTP/1.1
Cookie: name=admin; sessionId=abc123
- Servlet 容器(如 Tomcat)会解析请求头中的
Cookie
字段。 - 将 Cookie 数据转换为
javax.servlet.http.Cookie
对象数组,可通过request.getCookies()
获取。
Cookie[] cookies = req.getCookies();
if (cookies != null&& cookies.length > 0){
for (Cookie c : cookies) {
System.out.println(c.getName() + ": " + c.getValue());
}
}
Cookie的的有效期
默认当前的浏览器关闭失效.但我们可以手动设定cookie的有效时间,
在 Servlet 中,Cookie 的到期时间(Expiration) 由 setMaxAge(int seconds)
方法控制
到期时间的取值
正数 | 在指定秒数后过期, Cookie 持久化到客户端硬盘, |
---|---|
负数 | 浏览器关闭时自动删除(默认行为)。 |
0 | 立即删除 Cookie(需保证 name 、path 和 domain 与原 Cookie 一致)。 |
/* 到期时间:负整数 (默认值-1,表示只有在浏览器内存中存活,关闭浏览器失效*/
Cookie cookie = new Cookie("cookie", "cookie");
cookie.setMaxAge(-1);
resp.addCookie(cookie);
/*到期时间: 正整数 (表示存活指定秒数,会将数据存在磁盘中)*/
// 创建 Cookie 对象
Cookie cookie2 = new Cookie("cookie2", "cookie2");
// 设置有效期(单位:秒)
cookie2.setMaxAge(30); //存活30s
resp.addCookie(cookie2);
/*到期时间: 零 (表示删除cookie) */
Cookie cookie3 = new Cookie("cookie3", "cookie3");
// 删除 Cookie
cookie3.setMaxAge(0);
resp.addCookie(cookie3);
访问cookie03 cookie3已经删除
关闭浏览器 再访问cookie02 cookie失效
场景 | 设置方法 | 示例 |
---|---|---|
用户登录保持 | setMaxAge(7 * 24 * 3600) | 记住登录状态 7 天 |
临时会话数据 | setMaxAge(-1) (默认) | 购物车临时数据 |
强制退出登录 | setMaxAge(0) | 删除登录凭证 Cookie |
用户行为跟踪 | setMaxAge(365 * 24 * 3600) | 长期统计用户偏好 |
Cookie 路径
一、Cookie 路径的作用
通过 setPath() 方法设置 Cookie 的路径,可以控制该 Cookie 在哪些请求路径下会被浏览器发送到服务器。路径匹配规则基于请求的 URL 路径。
二、不同情景的代码示例与解释
情景一:服务器下所有项目共享 Cookie
域名下所有路径
// 当前项目路径为 S01
Cookie cookie = new Cookie("key", "value");
//当前服务器(域名)下的所有项目均可访问此 Cookie
cookie.setPath("/"); // 设置路径为根路径
response.addCookie(cookie);
当前服务器(域名)下的所有项目均可访问此 Cookie
情景二:仅当前项目内共享 Cookie(默认行为)
当前项目及其子路径
// 当前项目路径为 S01
Cookie cookie = new Cookie("key", "value");
// 设置路径为"/s01",表示当前项目下任何项目都可以访问到Cookie对象
cookie.setPath("/S01"); // 默认行为,可省略此设置
response.addCookie(cookie);
效果:
Cookie 的路径为 /S01,仅当访问 当前项目(S01)及其子路径 时才会发送 Cookie。
情景三:指定其他项目共享 Cookie
指定项目及其子路径
// 当前项目路径为 S01
Cookie cookie = new Cookie("key", "value");
cookie.setPath("/S02"); // 即使cookie是s01产生的,s01也不能获得它,只能在s02中获取
response.addCookie(cookie);
只能在s02中获取
情景四:子路径共享 Cookie
特定子路径及其下级路径
// 当前项目路径为 S01
Cookie cookie = new Cookie("key", "value");
cookie.setPath("/S01/sub"); // 只有在/S01/sub目录下才可以访问到Cookie对象
response.addCookie(cookie);
只有在/S01/sub目录下才可以访问
注意
Cookie 的存储范围限制
不能跨浏览器:Cookie 仅保存在当前浏览器中
不能跨域:Cookie 默认绑定到创建它的域名和路径(可通过 Domain 和 Path 属性调整
匹配规则:
域名(domain):
- 默认绑定到当前域名如 www.example.com)。
- 显式设置可共享到子域名
cookie.setDomain(".example.com"); // 子域名(如api.example.com)可访问
路径(path):
- 默认绑定到当前路径(如 /app)。
- 若设置 cookie.setPath(“/”),则所有路径均可访问。
cookie.setPath("/"); // 所有路径均可访问
有效期:
会话级 Cookie:不设置 maxAge,浏览器关闭后失效。
持久化 Cookie:设置 maxAge,长期有效直至过期。
跨域限制:
Cookie 不能跨浏览器
不能跨域发送(除非通过 CORS 策略显式允许且设置 withCredentials)。
Cookie 中存储中文的问题
中文编码:需使用 URLEncoder 编码,URLDecoder 解码
/**
*1.使用中文 要用 URLEncoder.encode() 进行编码,读取时用 URLDecoder.decode() 解码
*/
// 编码中文
String name = URLEncoder.encode("姓名", "UTF-8");
String value = URLEncoder.encode("张三", "UTF-8");
// 创建 Cookie
Cookie cookie = new Cookie(name, value);
response.addCookie(cookie);
// 解码(获取时)
Cookie[] cookies = request.getCookies();
for (Cookie c : cookies) {
String decodedName = URLDecoder.decode(c.getName(), "UTF-8");
String decodedValue = URLDecoder.decode(c.getValue(), "UTF-8");
}
同名 Cookie 的覆盖问题
若服务器发送重复的 Cookie(相同 Name + Domain + Path)会覆盖掉原来的Cookie
浏览器对 Cookie 的数量和大小限制
单个 Cookie ≤ 4KB,域名下 Cookie 总数通常 ≤ 150。
创建与发送的前提条件
- Cookie 已存储在浏览器中:
服务器通过response.addCookie()发送,客户端接收并保存 - Cookie 未过期
如果设置了maxAge,浏览器在有效期内保留Cookie,否则会话结束就删除 - 作用域匹配:
Domain和Path决定了Cookie发送的范围。 - 作用范围:
Cookie 默认绑定到域名和路径
HttpSession对象
HttpSession 是 Java Servlet 规范中用于 管理用户会话状态 的核心接口.因为session本身属于HTTP协议的范畴
它允许服务器在多个 HTTP 请求之间跟踪单个用户的状态,存储用户专属的临时数据
核心作用:
- 标识用户:通过唯一的 Session ID 关联多次请求。
- 共享数据:在同一会话中跨请求存储用户数据(如用户信息、临时配置)。
对于服务器而言,每一个连接到他的客户端都是一个session, servlet容器使用这个接口创建 http客户端和
http服务端之间的会话
标识符 JSESSIONID
Sesson是为了标识一次会话,那么该会话应有一个唯一的标志,这个标志就是sessionID, 客户端通过 Session ID 告诉服务器“我是谁”
存储方式:
默认:通过 Cookie 存储(如 JSESSIONID=ABC123)
备用:若 Cookie 被禁用,通过 URL 重写
JSESSIONID 的工作原理
Session ID 的传递方式
- 首次请求
-
服务器检查:用户首次访问服务器时,请求头中 不携带 JSESSIONID
-
创建 Session:未找到(如 Session 已过期/自己删除了),创建新 Session 并生成新 JSESSIONID。 ( 若找到对应 Session,复用现有数据 )
-
返回 Cookie:服务器通过响应头 Set-Cookie 发送给客户端。
HTTP/1.1 200 OK
Set-Cookie: JSESSIONID=ABC123; Path=/; HttpOnly
- 客户端存储:浏览器保存此 Cookie,后续请求自动携带。
- 后续请求(携带 JSESSIONID)
默认方式:
- 客户端请求:浏览器自动在请求头中附加通过JSESSIONID( Cookie 自动携带 )
GET /app/home HTTP/1.1
Cookie: JSESSIONID=ABC123
- 服务器识别:服务器通过 JSESSIONID 找到对应的 HttpSession,恢复用户会话数据
禁用 Cookie 时:若后续请求未携带,则认为客户端禁用了 Cookie。
自动切换至 URL 重写模式( 将 JSESSIONID 直接附加到 URL 的路径后),所有动态生成的链接需调用 response.encodeURL()
http://example.com/app/home;jsessionid=ABC123
### 客户端和服务器的“感知”本质
客户端的“感知”:
- 无法读取 Session 数据:
客户端只能看到 Session ID,无法直接访问服务器存储的会话数据(如用户邮箱、购物车内容)。
示例:就像你持有银行卡号,但无法直接查看账户余额或交易记录。
- 无法修改 Session 数据:
Session 数据完全由服务器管理,客户端无法篡改。即使恶意修改 Session ID,服务器也会因找不到对应数据而视为无效。
服务器的“感知”: 完全掌控 Session 数据
单机部署时,Session 通常存储在服务器内存中
服务器通过 Session ID 找到对应的 Session 对象,并管理其数据(如用户信息、会话时间等)。
服务器完全掌控 Session 内容,包括创建、修改和销毁。
HttpSession 的常用方法
package com.xxx.demo5;
import java.io.*;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.*;
import jakarta.servlet.annotation.*;
/**
* sesson对象的获取
* request.getSesson()
* 当获取session对象是,会先判断session对象是否存在,如果存在,则获取session()对象,
* 常用方法
* 获取session的会话标识符 getId()
* 获取session的会话标识符 getCreationTime()
* 获取最后一次访问的时间 getLastAccessedTime()
* 判断是否是新的session对象 isNew()
*/@WebServlet("/ser01")
public class Servlet01 extends HttpServlet{
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//创建session对象
HttpSession session = req.getSession();
//获取session的会话标识符
String id=session.getId();
System.out.println("id:"+id);
//获取session的会话标识符
System.out.println(session.getCreationTime());
//获取最后一次访问的时间
System.out.println(session.getLastAccessedTime());
//判断是否是新的session对象
System.out.println(session.isNew());
}
}
第一次访问,true 第二次false
session域对象
创建与获取
// 获取当前 Session,若不存在则创建新 Session
HttpSession session = request.getSession();
// 获取 Session 但不自动创建(若不存在返回 null)
HttpSession session = request.getSession(false);
数据存取
存储数据:
session.setAttribute("user", "admin"); // 键值对存储对象
读取数据:
String user = (String) session.getAttribute("user"); // 需强制类型转换
删除数据:
session.removeAttribute("user"); // 移除单个数据
Session 作用域与请求转发/重定向
场景 | Request 作用域 | Session 作用域 |
---|---|---|
请求转发 | ✅ 有效 | ✅ 有效 |
重定向 | ❌ 无效 | ✅ 有效 |
why 只要还是一个会话就不会失效
注意
Session的创建与存储:服务器生成Session ID,并通过Cookie发送给客户端。客户端存储这个ID,之后的请求都会带上它,服务器根据ID找到对应的session数据。
客户端和服务器感知的区别 : 客户端只知道Session ID,而服务器存储了实际的数据。
新浏览器无法获取旧session的原因 : Session ID存储在旧浏览器的Cookie中,新浏览器没有这个ID
session对象的销毁
1. 默认超时配置(Tomcat环境)
默认存活时间 : Tomcat中Session默认存活时间为 30分钟。基于不活动时间. 一旦操作 ,计时会重置。
修改默认时间 :
可修改Tomcat的conf/web.xml文件
<session-config>
<session-timeout>15</session-timeout> <!-- 修改为15分钟 -->
</session-config>
2. 自定义超时配置
设置超时:
setMaxInactiveInterval()
HttpSession session = request.getSession();
session.setMaxInactiveInterval(15); // 单位:秒(此处设为15秒)
查看当前超时时间:
int timeout = session.getMaxInactiveInterval(); // 返回单位为秒
3.立即销毁
通过 session,invalidata() 方法让 session 立即失效
session,invalidata()
4.关闭浏览器失效
session底层依赖cookie ,cookie对象默认只在浏览器中存活,关闭浏览器即失效
注意:
服务器端Session对象不会立即销毁,需等待超时(默认30分钟)。
客户端因丢失JSESSIONID,无法关联原Session,表现为新会话
5.关闭服务器
所有的东西都失效
-
默认行为:
关闭服务器(Tomcat/JVM终止)时,内存中所有Session对象立即销毁,未持久化的Session数据永久丢失。 -
持久化场景:
若配置了Session持久化(如保存到文件/数据库),服务器正常关闭时会将Session序列化到存储介质,重启后自动恢复。但需注意:
非默认配置:Tomcat默认不启用持久化,需手动配置Manager组件(如PersistentManager)。
异常关闭:服务器崩溃或强制终止时,Session数据仍会丢失。
概念 :
会话(Session):
用户与服务器的一次持续交互过程(如从登录到退出或超时)。
HttpSession 对象:
每个会话对应一个唯一的 HttpSession 对象,存储用户专属数据。
会话 ID:
通过 Cookie(默认 JSESSIONID)或 URL 重写标识用户会话
ServeletContext
每一个web应用有且仅有一个ServletContext对象,又称为Application对象 , 提供了一种在应用程序范围内共享数据的方式
从名称中可知,该对象是与应用程序相关的
在web容器启动时,会为每一个web应用程序创建一个对应的ServletContext对象
特点:在整个项目中就只有一个ServletContext对象
创建:tomcat一启动就会为部署在它上面的项目创建一个对应的全局管理者-ServletContext
销毁:tomcat一关闭就会销毁全局管理者-ServletContext
唯一性: 无论应用中有多少 Servlet、过滤器或监听器,它们共享同一个 ServletContext
核心作用: 它是整个 Web 应用的“全局管理中心”
共享数据: 作为域对象用来共享数据,此时的数据在整个应用程序中共享(如在线用户列表、缓存)。
访问配置:读取 web.xml 中的全局参数(如数据库连接信息)。
操作资源:获取应用内的文件路径、读取配置文件等。
生命周期管理:在应用启动/关闭时初始化或释放资源(如数据库连接池)。
在实现类中获取
//通过request获取
ServletContext servletContext = req.getServletContext();
//通过session获取
ServletContext servletContext1 = req.getSession().getServletContext();
//通过ServletConfig对象获取
ServletContext servletContext2 = getServletConfig().getServletContext();
//直接获取
ServletContext servletContext3 = getServletContext();
所有方式等价 : 无论哪种方式,最终获取的都是同一个 ServletContext 实例(应用全局唯一)。
适用场景:
优先使用方式(直接获取):代码最简洁。
在非 Servlet 类中(如监听器、过滤器):
- 监听器:通过 ServletContextEvent.getServletContext()。
- 过滤器:通过 FilterConfig.getServletContext()
避免滥用方式
(通过 HttpSession):除非已存在会话且需要同时操作会话数据
常用方法
//1.直接获取当前的版本信息
String serverInfo=req.getServletContext().getServerInfo();
System.out.println("当前的版本信息"+serverInfo);
//获得项目的真实路径
String realPath=req.getServletContext().getRealPath("/");
System.out.println("获取项目的真实路径"+realPath);
Cookie、Session 与 ServletContext 的关系与区别
用途
Cookie 用户身份标识、偏好设置
HttpSession 登录状态、购物车数据
ServletContext 全局计数器、数据库连接池配置
Cookie:用户身份标识与偏好设置
用途:
用户身份标识:通过存储 JSESSIONID 或自定义 Token(如 JWT)实现会话跟踪。
偏好设置:存储用户选择的语言、主题、时区等非敏感配置。
原因:
客户端存储:Cookie 数据由浏览器管理,可跨请求自动携带,适合轻量级、频繁访问的标识信息。
生命周期可控:通过 setMaxAge() 设置有效期,如长期记住用户偏好
跨路径/域名限制:通过 setPath() 和 setDomain() 控制作用范围,避免数据污染。
Session:登录状态与购物车数据
用途:
登录状态:用户认证后存储用户 ID、角色等敏感信息,维持会话。
购物车数据:临时保存用户选择的商品列表及数量,支持增删改查操作
原因:
服务器端安全性:Session 数据存储在内存或 Redis,避免客户端篡改(如购物车商品价格)
会话级隔离:每个用户拥有独立 Session,避免数据混淆(如不同用户的购物车)
自动过期机制:默认 30 分钟无活动销毁,防止长期占用资源
ServletContext:全局计数器与数据库连接池配置
用途:
全局计数器:统计在线用户数、网站访问量等全应用共享数据。
数据库连接池配置:存储连接池对象(如 HikariCP 实例),供所有 Servlet 复用。
原因:
应用级共享:ServletContext 生命周期与应用一致,适合长期存续的全局资源。
线程安全控制:需通过 synchronized 或原子类(如 AtomicInteger)管理全局计数器,避免并发问题。
配置集中管理:通过 web.xml 或注解加载数据库连接参数,统一维护
用户登录流程
步骤:
1.用户提交登录表单,服务器验证后创建 Session,存储用户信息。
2.通过 Set-Cookie 下发 JSESSIONID 至浏览器。
3.后续请求自动携带 Cookie,服务器通过 ID 恢复会话数据。
ServletContext 的角色 :记录全局登录用户数或在线状态。
Session和Cookie的区别
Session:保存在服务器,Session是一个对象保存在Java虚拟机中
保存的数据是Object
随着会话的结束而销毁
保存重要信息
Cookie:保存在浏览器
只能保存String类型,类似于文本文件,存放的都是数据,而不是对象
可以长期保存在浏览器,与会话无关
保存不重要信息