2022.5.9 Cookie、Session
Cookie 饼干
cookie 是 servlet 发送到 Web 浏览器的少量信息,这些信息由浏览器保存,然后发送回服务器。cookie 的值可以唯一地标识客户端,因此 cookie 常用于会话管理。
HTTP是无状态的协议,这意味着服务器无法确认用户的信息。于是乎,W3C就提出了:给每一个用户都发一个通行证,无论谁访问的时候都需要携带通行证,这样服务器就可以从通行证上确认用户的信息。通行证就是Cookie。
一个 cookie 拥有一个名称、一个值和一些可选属性,比如注释、路径和域限定符、最大生存时间和版本号
什么是 Cookie?
-
Cookie 翻译过来是饼干的意思。
-
Cookie 是服务器通知客户端保存键值对的一种技术。
-
客户端有了 Cookie 后,每次请求都发送给服务器。
-
每个 Cookie 的大小不能超过 4kb
如何创建 Cookie
新建model
标记文件夹
之后配置tomcat
BaseServlet
1 package com.xing.servlet; 2 3 import javax.servlet.ServletException; 4 import javax.servlet.http.HttpServlet; 5 import javax.servlet.http.HttpServletRequest; 6 import javax.servlet.http.HttpServletResponse; 7 import java.io.IOException; 8 import java.lang.reflect.Method; 9 10 public abstract class BaseServlet extends HttpServlet { 11 12 @Override 13 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 14 doPost(req, resp); 15 } 16 17 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 18 // 解决post请求中文乱码问题 19 // 一定要在获取请求参数之前调用才有效 20 req.setCharacterEncoding("UTF-8"); 21 // 解决响应中文乱码问题 22 resp.setContentType("text/html; charset=UTF-8"); 23 24 String action = req.getParameter("action"); 25 try { 26 // 获取action业务鉴别字符串,获取相应的业务 方法反射对象 27 Method method = this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class); 28 // System.out.println(method); 29 // 调用目标业务 方法 30 method.invoke(this, req, resp); 31 } catch (Exception e) { 32 e.printStackTrace(); 33 } 34 } 35 36 }
CookieServlet
1 package com.xing.servlet; 2 3 import com.xing.util.CookieUtils; 4 5 import javax.servlet.ServletException; 6 import javax.servlet.http.Cookie; 7 import javax.servlet.http.HttpServletRequest; 8 import javax.servlet.http.HttpServletResponse; 9 import java.io.IOException; 10 11 public class CookieServlet extends BaseServlet { 12 13 protected void createCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 14 //1 创建Cookie对象 15 Cookie cookie = new Cookie("key1", "value1"); 16 //2 服务器通知客户端保存Cookie 17 resp.addCookie(cookie); 18 resp.getWriter().write("Cookie创建成功"); 19 } 20 }
web.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" 5 version="4.0"> 6 7 <servlet> 8 <servlet-name>CookieServlet</servlet-name> 9 <servlet-class>com.xing.servlet.CookieServlet</servlet-class> 10 </servlet> 11 <servlet-mapping> 12 <servlet-name>CookieServlet</servlet-name> 13 <url-pattern>/cookieServlet</url-pattern> 14 </servlet-mapping> 15 </web-app>
cookie.html
1 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 2 <html> 3 <head> 4 <meta http-equiv="pragma" content="no-cache" /> 5 <meta http-equiv="cache-control" content="no-cache" /> 6 <meta http-equiv="Expires" content="0" /> 7 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 8 <title>Cookie</title> 9 <base href="http://localhost:8080/cookie_session/"> 10 <style type="text/css"> 11 12 ul li { 13 list-style: none; 14 } 15 16 </style> 17 </head> 18 <body> 19 <iframe name="target" width="500" height="500" style="float: left;"></iframe> 20 <div style="float: left;"> 21 <ul> 22 <!--调用cookieServlet请求中的createCookie方法--> 23 <li><a href="cookieServlet?action=createCookie" target="target">Cookie的创建</a></li> 24 <li><a href="cookieServlet?action=getCookie" target="target">Cookie的获取</a></li> 25 <li><a href="cookieServlet?action=updateCookie" target="target">Cookie值的修改</a></li> 26 <li>Cookie的存活周期</li> 27 <li> 28 <ul> 29 <li><a href="cookieServlet?action=defaultLife" target="target">Cookie的默认存活时间(会话)</a></li> 30 <li><a href="cookieServlet?action=deleteNow" target="target">Cookie立即删除</a></li> 31 <li><a href="cookieServlet?action=life3600" target="target">Cookie存活3600秒(1小时)</a></li> 32 </ul> 33 </li> 34 <li><a href="cookieServlet?action=testPath" target="target">Cookie的路径设置</a></li> 35 <li><a href="" target="target">Cookie的用户免登录练习</a></li> 36 </ul> 37 </div> 38 </body> 39 </html>
访问http://localhost:8080/cookie_session/cookie.html
服务器如何获取 Cookie
服务器获取客户端的 Cookie 只需要一行代码:Cookie[] cookie = req.getCookies();
1 package com.xing.servlet; 2 3 4 import com.xing.util.CookieUtils; 5 6 import javax.servlet.ServletException; 7 import javax.servlet.http.Cookie; 8 import javax.servlet.http.HttpServletRequest; 9 import javax.servlet.http.HttpServletResponse; 10 import java.io.IOException; 11 12 public class CookieServlet extends BaseServlet { 13 14 protected void getCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 15 16 Cookie[] cookies = req.getCookies(); 17 for (Cookie cookie : cookies) { 18 // getName方法返回Cookie的key(名) 19 // getValue方法返回Cookie的value值 20 resp.getWriter().write("Cookie[" + cookie.getName() + "=" + cookie.getValue() + "] <br/>"); 21 } 22 } 23 }
查找指定cookie
CookieUtils
1 package com.xing.util; 2 3 import javax.servlet.http.Cookie; 4 5 public class CookieUtils { 6 /** 7 * 查找指定名称的Cookie对象 8 */ 9 public static Cookie findCookie(String name , Cookie[] cookies){ 10 if (name == null || cookies == null || cookies.length == 0) { 11 return null; 12 } 13 14 for (Cookie cookie : cookies) { 15 if (name.equals(cookie.getName())) { 16 return cookie; 17 } 18 } 19 return null; 20 } 21 }
CookieServlet
1 package com.xing.servlet; 2 3 4 import com.xing.util.CookieUtils; 5 6 import javax.servlet.ServletException; 7 import javax.servlet.http.Cookie; 8 import javax.servlet.http.HttpServletRequest; 9 import javax.servlet.http.HttpServletResponse; 10 import java.io.IOException; 11 12 public class CookieServlet extends BaseServlet { 13 14 protected void getCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 15 16 Cookie[] cookies = req.getCookies(); 17 Cookie iWantCookie = CookieUtils.findCookie("key1", cookies); 18 // 如果不等于null,说明赋过值,也就是找到了需要的Cookie 19 if (iWantCookie != null) { 20 resp.getWriter().write("找到了需要的Cookie"); 21 } 22 } 23 }
Cookie 值的修改
值不支持中文等一些特殊字符
方案一:
-
先创建一个要修改的同名(指的就是 key)的 Cookie 对象
-
在构造器,同时赋于新的 Cookie 值。
-
调用 response.addCookie( Cookie );
1 protected void updateCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 2 // 方案一: 3 // 1、先创建一个要修改的同名的Cookie对象(修改的cookie的key要相同),在构造器,同时赋于新的Cookie值。 4 Cookie cookie = new Cookie("key1","newValue1"); 5 // 2、调用response.addCookie( Cookie ); 通知 客户端 保存修改 6 resp.addCookie(cookie); 7 resp.getWriter().write("key1的Cookie已经修改好"); 8 9 }
方案二:
-
先查找到需要修改的 Cookie 对象
-
调用 setValue()方法赋于新的 Cookie 值。
-
调用 response.addCookie()通知客户端保存修改
1 protected void updateCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 2 // 方案二: 3 // 1、先查找到需要修改的Cookie对象 4 Cookie cookie = CookieUtils.findCookie("key2", req.getCookies()); 5 if (cookie != null) { 6 // 2、调用setValue()方法赋于新的Cookie值。 7 cookie.setValue("newValue2"); 8 // 3、调用response.addCookie()通知客户端保存修改 9 resp.addCookie(cookie); 10 } 11 resp.getWriter().write("key1的Cookie已经修改好"); 12 13 }
Cookie 生命控制
Cookie 的生命控制指的是如何管理 Cookie 什么时候被销毁(删除)
setMaxAge() :设置cookie的最大生存时间,以秒为单位。
-
正数,表示在指定的秒数后过期
-
负数,表示浏览器一关,Cookie 就会被删除(默认值是-1 session级别)
-
零,表示马上删除 Cookie
1 /** 2 * 默认的会话级别的Cookie 3 * @param req 4 * @param resp 5 * @throws ServletException 6 * @throws IOException 7 */ 8 protected void defaultLife(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 9 Cookie cookie = new Cookie("defalutLife","defaultLife"); 10 //默认就是-1,其实不用自己设置 11 cookie.setMaxAge(-1);//设置存活时间 12 resp.addCookie(cookie); 13 }
1 /** 2 * 马上删除一个Cookie 3 * @param req 4 * @param resp 5 * @throws ServletException 6 * @throws IOException 7 */ 8 protected void deleteNow(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 9 // 先找到你要删除的Cookie对象 10 Cookie cookie = CookieUtils.findCookie("key4", req.getCookies()); 11 if (cookie != null) { 12 // 调用setMaxAge(0); 13 cookie.setMaxAge(0); // 表示马上删除,都不需要等待浏览器关闭 14 // 调用response.addCookie(cookie); 15 resp.addCookie(cookie); 16 17 resp.getWriter().write("key4的Cookie已经被删除"); 18 } 19 20 }
1 /** 2 * 设置存活1个小时的Cooie 3 * @param req 4 * @param resp 5 * @throws ServletException 6 * @throws IOException 7 */ 8 protected void life3600(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 9 10 Cookie cookie = new Cookie("life3600", "life3600"); 11 cookie.setMaxAge(60 * 60); // 设置Cookie一小时之后被删除。无效 12 resp.addCookie(cookie); 13 resp.getWriter().write("已经创建了一个存活一小时的Cookie"); 14 15 }
Cookie 有效路径 Path 的设置
Cookie 的 path 属性可以有效的过滤哪些 Cookie 可以发送给服务器。哪些不发。 path 属性是通过请求的地址来进行有效的过滤。
CookieA path=/工程路径
CookieB path=/工程路径/abc
-
请求地址如下: http://ip:port/工程路径/a.html
-
CookieA 发送
-
CookieB 不发送
-
-
请求地址如下: http://ip:port/工程路径/abc/a.html
-
CookieA 发送
-
CookieB 发送
-
1 protected void testPath(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 2 Cookie cookie = new Cookie("path1", "path1"); 3 // getContextPath() ===>>>> 得到工程路径 4 cookie.setPath( req.getContextPath() + "/abc" ); // ===>>>> /工程路径/abc 5 resp.addCookie(cookie); 6 resp.getWriter().write("创建了一个带有Path路径的Cookie"); 7 }
但是没有显示
因为我们访问的是 http://localhost:8080/cookie_session/cookie.html,不符合cookie的path路径格式
Cookie 练习
免输入用户名登录(就是网页自动保存了你的用户名)
login.jsp
1 <%@ page contentType="text/html;charset=UTF-8" language="java" %> 2 <html> 3 <head> 4 <title>Title</title> 5 </head> 6 <body> 7 <form action="http://localhost:8080/cookie_session/loginServlet" method="get"> 8 用户名:<input type="text" name="username" value="${cookie.username.value}"> <br> 9 密码:<input type="password" name="password"> <br> 10 <input type="submit" value="登录"> 11 </form> 12 </body> 13 </html>
web.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" 5 version="4.0"> 6 <servlet> 7 <servlet-name>LoginServlet</servlet-name> 8 <servlet-class>com.xing.servlet.LoginServlet</servlet-class> 9 </servlet> 10 <servlet-mapping> 11 <servlet-name>LoginServlet</servlet-name> 12 <url-pattern>/loginServlet</url-pattern> 13 </servlet-mapping> 14 15 </web-app>
LoginServlet
1 package com.xing.servlet; 2 3 import javax.servlet.ServletException; 4 import javax.servlet.http.Cookie; 5 import javax.servlet.http.HttpServlet; 6 import javax.servlet.http.HttpServletRequest; 7 import javax.servlet.http.HttpServletResponse; 8 import java.io.IOException; 9 10 public class LoginServlet extends HttpServlet { 11 12 @Override 13 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 14 String username = req.getParameter("username"); 15 String password = req.getParameter("password"); 16 17 if ("admin".equals(username) && "123456".equals(password)) { 18 //登录 成功 19 Cookie cookie = new Cookie("username", username); 20 cookie.setMaxAge(60 * 60 * 24 * 7);//当前Cookie一周内有效 21 resp.addCookie(cookie); 22 System.out.println("登录 成功"); 23 } else { 24 // 登录 失败 25 System.out.println("登录 失败"); 26 } 27 28 } 29 }
访问http://localhost:8080/cookie_session/login.jsp
Session 会话
什么是 Session 会话?
-
Session 就一个接口(HttpSession)。
-
Session 就是会话。它是用来维护一个客户端和服务器之间关联的一种技术。
-
每个客户端都有自己的一个 Session 会话。
-
Session 会话中,我们经常用来保存用户登录之后的信息。
cookie保存在客户端,session保存在服务器端
如何创建 Session 和获取(id 号,是否为新)
如何创建和获取 Session。它们的 API 是一样的。 request.getSession()
-
第一次调用是:创建 Session 会话
-
之后调用都是:获取前面创建好的 Session 会话对象。
isNew():判断到底是不是刚创建出来的(新的)
-
true 表示刚创建
-
false 表示获取之前创建
每个会话都有一个身份证号。也就是 ID 值。而且这个 ID 是唯一的。
getId() :得到 Session 的会话 id 值。
Session的创建和获取
BaseServlet
1 package com.xing.servlet; 2 3 import javax.servlet.ServletException; 4 import javax.servlet.http.HttpServlet; 5 import javax.servlet.http.HttpServletRequest; 6 import javax.servlet.http.HttpServletResponse; 7 import java.io.IOException; 8 import java.lang.reflect.Method; 9 10 public abstract class BaseServlet extends HttpServlet { 11 12 @Override 13 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 14 doPost(req, resp); 15 } 16 17 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 18 // 解决post请求中文乱码问题 19 // 一定要在获取请求参数之前调用才有效 20 req.setCharacterEncoding("UTF-8"); 21 // 解决响应中文乱码问题 22 resp.setContentType("text/html; charset=UTF-8"); 23 24 String action = req.getParameter("action"); 25 try { 26 // 获取action业务鉴别字符串,获取相应的业务 方法反射对象 27 Method method = this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class); 28 // System.out.println(method); 29 // 调用目标业务 方法 30 method.invoke(this, req, resp); 31 } catch (Exception e) { 32 e.printStackTrace(); 33 } 34 } 35 36 }
SessionServlet
1 package com.xing.servlet; 2 3 import javax.servlet.ServletException; 4 import javax.servlet.http.HttpServletRequest; 5 import javax.servlet.http.HttpServletResponse; 6 import javax.servlet.http.HttpSession; 7 import java.io.IOException; 8 9 public class SessionServlet extends BaseServlet { 10 11 protected void createOrGetSession(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 12 // 创建和获取Session会话对象,首次是创建 13 HttpSession session = req.getSession(); 14 // 判断 当前Session会话,是否是新创建出来的 15 boolean isNew = session.isNew(); 16 // 获取Session会话的唯一标识 id 17 String id = session.getId(); 18 19 resp.getWriter().write("得到的Session,它的id是:" + id + " <br /> "); 20 resp.getWriter().write("这个Session是否是新创建的:" + isNew + " <br /> "); 21 22 } 23 }
web.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" 5 version="4.0"> 6 7 <servlet> 8 <servlet-name>SessionServlet</servlet-name> 9 <servlet-class>com.xing.servlet.SessionServlet</servlet-class> 10 </servlet> 11 <servlet-mapping> 12 <servlet-name>SessionServlet</servlet-name> 13 <url-pattern>/sessionServlet</url-pattern> 14 </servlet-mapping> 15 16 </web-app>
session.html
1 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 2 <html> 3 <head> 4 <meta http-equiv="pragma" content="no-cache" /> 5 <meta http-equiv="cache-control" content="no-cache" /> 6 <meta http-equiv="Expires" content="0" /> 7 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 8 <title>Session</title> 9 <base href="http://localhost:8080/cookie_session/"> 10 <style type="text/css"> 11 12 ul li { 13 list-style: none; 14 } 15 16 </style> 17 </head> 18 <body> 19 <iframe name="target" width="500" height="500" style="float: left;"></iframe> 20 <div style="float: left;"> 21 <ul> 22 <li><a href="sessionServlet?action=createOrGetSession" target="target">Session的创建和获取(id号、是否为新创建)</a></li> 23 <li><a href="sessionServlet?action=setAttribute" target="target">Session域数据的存储</a></li> 24 <li><a href="sessionServlet?action=getAttribute" target="target">Session域数据的获取</a></li> 25 <li>Session的存活</li> 26 <li> 27 <ul> 28 <li><a href="sessionServlet?action=defaultLife" target="target">Session的默认超时及配置</a></li> 29 <li><a href="sessionServlet?action=life3" target="target">Session3秒超时销毁</a></li> 30 <li><a href="sessionServlet?action=deleteNow" target="target">Session马上销毁</a></li> 31 </ul> 32 </li> 33 <li><a href="" target="target">浏览器和Session绑定的原理</a></li> 34 </ul> 35 </div> 36 </body> 37 </html>
访问 http://localhost:8080/cookie_session/session.html
首次点击时创建session
第二次点击是获取前面的
Session 域数据的存取
1 /** 2 * 往Session中保存数据 3 * @param req 4 * @param resp 5 * @throws ServletException 6 * @throws IOException 7 */ 8 protected void setAttribute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 9 req.getSession().setAttribute("key1", "value1"); 10 resp.getWriter().write("已经往Session中保存了数据"); 11 12 } 13 14 15 /** 16 * 获取Session域中的数据 17 * @param req 18 * @param resp 19 * @throws ServletException 20 * @throws IOException 21 */ 22 protected void getAttribute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 23 Object attribute = req.getSession().getAttribute("key1"); 24 resp.getWriter().write("从Session中获取出key1的数据是:" + attribute); 25 }
Session 生命周期控制
-
public void setMaxInactiveInterval(int interval) 设置 Session 的超时时间(以秒为单位),超过指定的时长,Session 就会被销毁。
-
值为正数的时候,设定 Session 的超时时长。
-
负数表示永不超时(极少使用)
-
-
public int getMaxInactiveInterval()获取 Session 的超时时间
Session 默认的超时时长是多少! Session 默认的超时时间长为 30 分钟。
1 protected void defaultLife(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 2 // 获取了Session的默认超时时长 3 int maxInactiveInterval = req.getSession().getMaxInactiveInterval(); 4 5 resp.getWriter().write("Session的默认超时时长为:" + maxInactiveInterval + " 秒 "); 6 7 }
因为在 Tomcat 服务器的配置文件 web.xml中默认有以下的配置
它就表示配置了当前 Tomcat 服务器下所有的 Session 超时配置默认时长为:30 分钟。
设置整个项目时长
如果说。你希望你的 web 工程,默认的 Session 的超时时长为其他时长。你可以在你自己的 web.xml 配置文件中配置。就可以修改你的 web 工程所有 Seession 的默认超时时长。
web.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" 5 version="4.0"> 6 <servlet> 7 <servlet-name>SessionServlet</servlet-name> 8 <servlet-class>com.xing.servlet.SessionServlet</servlet-class> 9 </servlet> 10 <servlet-mapping> 11 <servlet-name>SessionServlet</servlet-name> 12 <url-pattern>/sessionServlet</url-pattern> 13 </servlet-mapping> 14 15 16 <!--表示当前web工程。创建出来的所有Session默认是20分钟 超时时长--> 17 <session-config> 18 <session-timeout>20</session-timeout> 19 </session-config> 20 </web-app>
修改个别时长
如果你想只修改个别 Session 的超时时长。就可以使用setMaxInactiveInterval(int interval)单独设置超时时长。
1 protected void life3(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 2 // 先获取Session对象 3 HttpSession session = req.getSession(); 4 // 设置当前Session3秒后超时 5 session.setMaxInactiveInterval(3); 6 7 resp.getWriter().write("当前Session已经设置为3秒后超时"); 8 }
让当前 Session 会话马上超时无效
1 public void invalidate() 让当前 Session 会话马上超时无效。 2 3 protected void deleteNow(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 4 // 先获取Session对象 5 HttpSession session = req.getSession(); 6 // 让Session会话马上超时 7 session.invalidate(); 8 9 resp.getWriter().write("Session已经设置为超时(无效)"); 10 }
浏览器和 Session 之间关联的技术内幕
为什么session没有超时,关闭浏览器后session就失效了 ?因为Session 技术,底层其实是基于 Cookie 技术来实现的,浏览器一关,cookie就没有了。
1、清除所有cookie
2、创建一个session,返回cookie,cookie中value有session的id
3、每次发送请求都会将cookie发送给服务器,服务器通过Cookie中的session的id值找到自已之前创连好的Session并返回