一.Cookie和Session
Cookie和Session都是用于在Web应用中跟踪用户状态的技术。Cookie是存储在用户浏览器中的小文本文件,由服务器发送给浏览器。当用户再次访问同一网站时,浏览器会把Cookie信息发送回服务器。例如,网站可以利用Cookie记住用户的登录状态、语言偏好等信息。Cookie有一定的有效期,可以设置过期时间。Session是存储在服务器端的数据结构,用于跟踪用户的会话状态。服务器为每个用户(通常是通过用户的首次请求)创建一个Session,会给用户分配一个唯一的标识符(Session ID),这个ID一般通过Cookie或URL参数等方式传递给浏览器。当用户在网站的不同页面之间跳转时,浏览器会发送Session ID,服务器根据这个ID来识别用户并获取对应的会话数据,如购物车中的商品信息等。
二.Cookie和Session的联系与区别
1.cookie是什么
在浏览器访问服务器之前,此时你的浏览器对于这个服务器是一无所知的,你的浏览器上是没有任何和这个服务器相关的数据的。在网页开发中用户获取数据和服务器发送数据会产生很多“临时性”的数据。临时性的数据有的可以放在服务器这边存储,有的可以放在浏览器上,用户下次用可以直接获取到。
比如哔哩哔哩中倍速播放,蓝光模式这种数据就是临时数据,用户下次再点开还是倍速蓝光。
浏览器要保存数据为什么要放在cookie上,直接放硬盘上不行吗?
答案:不行,如果让网页能轻易的访问你的系统文件是非常危险的有可能会中病毒让电脑奔溃或者数据删掉。为了保证安全浏览器会对网页的功能做出限制,禁止访问硬盘。为了能保证安全又能存储数据,浏览器就提供了cookie功能。
cookie是按照键值对的方式存储一些字符串。这些键值对往往是服务器返回来的。浏览器把这些键值对按照域名进行分类存储,不同的网站cookie是独立的。这些cookie的内容是程序员自己定义的。
一个网站中cookie中会存储很多键值对,往往会有一个很重要的键值对,用来统计用户的信息。为了实现身份识别的效果,不仅仅需要cookie来支持,在服务器这边也需要session来支持。
2.举例
假设你是第一次来医院看病,首次挂号的时候,医院会让你办一张就诊卡。同时在医院的系统里面会给你创建一份电子的档案。当你排了半天队,见到医生,医生让你刷你的就诊卡,你一刷卡你的各种信息就显示在医生的电脑上了。(就诊卡里面存了你的身份标识,存了一串字符串,就像电话号码一样),电子档案可以想象成哈希表,key是你的身份标识,value是你的电子档案详情。刷卡的时候读卡器读到我的身份标识就可以知道我的电子档案的详情了。然后医生让你去抽血,做B超,尿检。到了抽血科,医生也是让先刷卡,刷卡后知道你的病就知道要抽多少血哪里的血。来到B超科后同样先刷卡拿到你的信息,就知道怎么检查。检查完毕后医生还得刷卡拿信息取药。当你下一次来的时候医生可以直接系统里面拿到你的信息和之前的取药结果。
首次访问网站登录成功后相当于网站给你一个就诊卡(身份标识,身份标识也叫sessionid),身份标识就通过服务器返回给浏览器的响应,保存在浏览器的cookie中了。与此同时人家网站服务器这边也会创建出一个对应的session(电子档案),session中会记录你的信息。网站服务器有很多个用户,每个用户都有自己的session,他们的sessionid各不相同,服务器会使用类似于HASH表这样的方式,以sessionid为key,以session为value,把所有数据组织起来。后续访问网站的其他页面(相当于到各个科室做检查),都会在请求的cookie字段中,带上刚才这里的sessionid(也就是做检查先刷卡,判断你的信息),服务器就知道你当前的用户信息了。
我们通过抓包可以看到cookie里面的主要内容:
是以键值对的方式去存储的。键值对之间使用;分割,键和值使用=分割。在cookie中其中一个键值对是表示身份标识的。
3.Session
session存在的意义也是为了让用户能够保存一些自定义数据,此时的session更像是一个Map<String,Object>。session在一个服务器上可以存在很多份,每个用户都应该有一个自己的session,应该服务器有多个用户,服务器就会用map的方式组织session.
4.总结
Cookie 是浏览器在本地持久化存储数据的一种机制。
1.Cookie的数据从哪里来?服务器返回给浏览器的。
2.Cookie的数据长啥样?Cookie 中是键值对结构的数据.并且这里的键值对都是程序员自定义的。
3.Cookie有什么作用?Cookie 就可以在浏览器这边存储一些“临时性的数据”,其中最典型的一种使用方式,就是用来存储“身份标识”。
4.Cookie到哪里去?Cookie的内容会在下次访问该网站的时候,自动的被带到HTTP请求中。
5.Cookie怎么存的?浏览器按照不同的“域名”分别存储Cookie,域名和域名之间的Cookie是不能干扰的Cookie 存储在硬盘上的。Cookie存储往往会有一个超时时间。
Cookie的超时时间也叫过期时间,是指浏览器存储Cookie的有效时长。当服务器发送一个Cookie给浏览器时,会设置这个Cookie的相关属性,其中就包括过期时间。如果没有设置超时时间,Cookie就会成为会话Cookie,它会在浏览器会话期间(即浏览器打开到关闭的时间段)一直存在,一旦浏览器关闭,会话Cookie就会被删除。 要是设置了具体的超时时间,浏览器会根据这个时间来存储Cookie。例如,设置超时时间为1小时,那么从Cookie被设置开始计算,1个小时后,浏览器会自动删除这个Cookie,之后对相应网站的请求就不会再带上这个已经过期的Cookie。这样的机制可以控制用户数据在客户端存储的周期,用于实现如用户登录状态保持一定时间等功能。
二.核心方法
HttpServletRequest 类中的相关方法
HttpServletResponse类中的相关方法
HttpSession 类中的相关方法
一个 HttpSession 对象里面包含多个键值对. 我们可以往 HttpSession 中存任何我们需要的信息。
Cookie 类中的相关方法
HTTP 的 Cooke 字段中存储的实际上是多组键值对. 每个键值对在 Servlet 中都对应了一个 Cookie
对象。
通过 HttpServletRequest.getCookies() 获取到请求中的一系列 Cookie 键值对。
通过 HttpServletResponse.addCookie() 可以向响应中添加新的 Cookie 键值对。
1.获取cookie
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;
import java.util.Enumeration;
class User{
public String username;
public int age;
}
@WebServlet("/hello1")
public class HelloSevert extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Cookie cookie = new Cookie("date","2024-10-24");
resp.addCookie(cookie);
Cookie cookie1 = new Cookie("date1","2024-10-25");
resp.addCookie(cookie1);
resp.getWriter().write("ok");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Cookie[] cookies = req.getCookies();
for(Cookie x:cookies)
{
System.out.println(x.getName()+":"+x.getValue());
}
}
}
通过抓包继续观察
2.获取session
代码示例: 实现用户登陆
实现简单的用户登陆逻辑
这个代码中主要是通过 HttpSession 类完成. 并不需要我们手动操作 Cookie 对象。
import com.fasterxml.jackson.databind.ObjectMapper;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.util.Enumeration;
class User{
public String username;
public int age;
}
@WebServlet("/hello1")
public class HelloSevert extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String user = req.getParameter("username");
String password = req.getParameter("password");
if(user==null||password==null||user.equals("")||password.equals("")){
resp.setContentType("text/html,charset=utf8");
resp.getWriter().write("用户名错误");
return;
}
if(user.equals("aaa")&&password.equals("123")){
HttpSession session = req.getSession(true);
session.setAttribute("username",user);
session.setAttribute("time",System.currentTimeMillis());
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
if(session==null)
{
return;
}
String user = (String)session.getAttribute("username");
System.out.println("user:"+user);
}
}
HttpSession session = req.getSession(true);参数为true不存在会话就创建,存在会话就直接查询。参数为false不存在就返回null,存在就直接查询。
getSession 背后做的事情:
1.先读取请求中的Cookie,看Cookie 里是否有JSESSIONID属性,以及值是啥。如果没有,就认为需要创建新会话。如果有,就拿着这个id去查询看看当前的session 是否存在,要是 session存在,就直接返回该 session,要是session不存在,就准备创建新会话。
2.当前确实需要创建会话,就会创建出一个Session 对象,同时生成一个唯一的JSESSIONID。
以JSESSIONID为key,Session对象为value,把这个键值对给插入到服务器 上述的哈希表
3.刚才生成的JSESSIONID又会通过addCookie方法,加入到响应中。此时响应里就会带有Set-Cookie字段,这里的值就是JSESSION=xxxxxxxxx通过响应,就把JSESSIONID返回到浏览器这边了。