Cookie & Session
一. 会话技术
1. 定义
- 一次会话中包含多次请求和响应。
- 一次会话:浏览器第一次给服务器资源发送请求时,会话建立,直到有一方断开为止。
2. 功能
HTTP 是无状态的,每次请求之间相互独立,不能交换数据。
在一次会话的范围内(多次请求之间)共享数据。
3. 方式
- 客户端会话技术:Cookie
- 服务器端会话技术:Session
二. Cookie
1. 概念
客户端会话技术,将数据保存到客户端。
2. 使用
- 创建 Cookie 对象,绑定数据:
new Cookie(String name, String value)
- 发送 Cookie 对象:
response.addCookie(Cookie cookie)
- 获取 Cookie 对象,获得数据:
Cookie[] request.getCookies()
@WebServlet("/cookieDemo1")
public class CookieDemo1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 创建 Cookie 对象,绑定数据
Cookie cookie = new Cookie("msg", "hello");
// 2. 发送 Cookie 对象
response.addCookie(cookie);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
@WebServlet("/cookieDemo2")
public class CookieDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 3. 获取 Cookie 对象,获得数据
Cookie[] cookies = request.getCookies();
if(cookies != null) {
for (Cookie cookie : cookies) {
String name = cookie.getName();
String value = cookie.getValue();
System.out.println(name + "=" + value);
}
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
3. 实现原理
基于响应头 Set-Cookie
和请求头 Cookie
实现。
4. 细节
1.一次可以发送多个 Cookie
- 创建多个 Cookie 对象,调用
addCookie()
分别添加至 response 发送。 - 如果对同一个 Cookie 对象多次赋值,其值会被覆盖。
@WebServlet("/cookieDemo3")
public class CookieDemo3 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 创建 Cookie 对象,绑定数据
Cookie cookie1 = new Cookie("msg", "hello");
Cookie cookie2 = new Cookie("name", "hjplz");
// 2. 发送 Cookie 对象
response.addCookie(cookie1);
response.addCookie(cookie2);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
2.Cookie 在浏览器中的保存时间
- 在默认情况下,关闭浏览器后,Cookie 数据被销毁。
- 持久化存储:
setMaxAge(int expiry)
- 正数:将 Cookie 数据写到硬盘的文件中,存活时间为 expiry 秒。
- 负数:默认情况
- 0:删除 Cookie 信息
@WebServlet("/cookieDemo4")
public class CookieDemo4 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 创建 Cookie 对象,绑定数据
Cookie cookie = new Cookie("msg", "setMaxAge");
// 2. 设置 Cookie 的存活时间
cookie.setMaxAge(30); // 将 Cookie 数据写到硬盘的文件中,存活时间为30秒
// cookie.setMaxAge(-1); // 默认情况
// cookie.setMaxAge(0); // 删除 Cookie 信息
// 3. 发送 Cookie 对象
response.addCookie(cookie);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
3.Cookie 存储中文
- 在 Tomcat 8 之前,不能在 Cookie 中直接存储中文数据,需要将中文数据转码,一般采用 URL 编码(%E3)。
- 在 Tomcat 8 之后,在 Cookie 中可以直接存储中文数据,但不支持特殊字符,建议使用 URL 编码存储 & 解析特殊字符。
@WebServlet("/cookieDemo5")
public class CookieDemo5 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 创建 Cookie 对象,绑定数据
Cookie cookie = new Cookie("msg", "你好");
// 2. 发送 Cookie 对象
response.addCookie(cookie);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
4.Cookie 共享问题
- 在一个 Tomcat 服务器中部署的多个 web 项目之间共享 Cookie 信息
- 在默认情况下,不能共享 Cookie 信息。
- 通过
setPath(String path)
设置 Cookie 的共享范围为 “/”,默认值是当前的虚拟目录(Context Path)。
@WebServlet("/cookieDemo6")
public class CookieDemo6 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 创建 Cookie 对象,绑定数据
Cookie cookie = new Cookie("msg", "你好");
// 2. 设置 path,让当前服务器下部署的所有项目共享 Cookie 信息
cookie.setPath("/");
// 3. 发送 Cookie 对象
response.addCookie(cookie);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
- 在不同的 Tomcat 服务器中部署的 web 项目之间共享 Cookie 信息
- 通过
setDomain(String path)
设置一级域名相同,来实现在多个服务器之间共享 Cookie 信息。e.g.setDomain(".baidu.com")
,tieba.baidu.com 和 news.baidu.com 之间可以共享 Cookie 信息。
- 通过
5. 特点 & 作用
1.特点
- 在客户端浏览器存储 Cookie 数据
- 浏览器对于单个 Cookie 的大小有限制(4KB),对于同一个域名下的总 Cookie数量有限制(20个)。
2.作用
- 存储少量 & 不太敏感的数据
- 在用户不登录的情况下,完成服务器对客户端的身份识别。
6. 案例:记住上一次访问时间
三. Session
1. 概念
服务器端会话技术,将数据保存到服务器端的 HttpSession 对象中。
2. 使用
1.获取 HttpSession 对象:HttpSession session = request.getSession();
2.使用 HttpSession 对象
Object getAttribute(String name)
void setAttribute(String name, Object value)
void removeAttribute(String name)
@WebServlet("/sessionDemo1")
public class SessionDemo1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 获取 Session
HttpSession session = request.getSession();
// 2. 存储数据
session.setAttribute("msg", "Hello Session!");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
@WebServlet("/sessionDemo2")
public class SessionDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 3. 获取存在 Session 中的数据并打印
System.out.println(request.getSession().getAttribute("msg"));
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
3. 实现原理
Session 的实现依赖于 Cookie。
4. 细节
1.当客户端关闭,服务器不关闭,两次获取的 Session 在默认情况下不是同一个(因为不是同一个会话)。
- 如果要持久化保存 Session, 可以设置 JSESSIONID 的 Cookie。
@WebServlet("/sessionDemo3") public class SessionDemo3 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获取 Session HttpSession session = request.getSession(); // 客户端关闭 1 min 之内,能获得相同的 Session Cookie cookie = new Cookie("JSESSIONID", session.getId()); cookie.setMaxAge(60 * 60); // 1 min response.addCookie(cookie); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }
2.当客户端不关闭,服务器关闭,两次获取的 Session 在默认情况下不是同一个。为了确保数据不丢失,Tomcat 自动完成以下工作:
- Session 的钝化:在服务器正常关闭之前,将 Session 对象序列化到硬盘上。
- Session 的活化:在服务器启动后,将 Session 文件转化为内存中的 Session 对象。
3.Session 的失效时间:默认为 30 mins
-
服务器关闭
-
Session 对象调用
invalidate()
-
修改配置文件 web.xml,指定失效时间。
<session-config> <session-timeout>30</session-timeout> </session-config>
5. 特点
1.在服务器端存储一次会话的多次请求的数据。
2.可以存储任意类型、任意大小的数据。
3.与 Cookie 的区别
- Session 存储数据在服务器端,Cookie 存储数据在客户端。
- Session 没有数据大小限制,Cookie 有。
- Session 数据安全,Cookie 相对不安全。