谁在跟http会话,该跟谁会话了——Cookie + Session机制
(1)Cookie角度
Cookie是浏览器-服务器之间的:
浏览器需要保存Cookie,在合适的请求中携带Cookie,表现为HTTP请求头中的Cookie Header
服务器生成Cookie并传递给浏览器,表现为响应头中的set Cookie
用户第一次登录——>服务端为该用户生成一个Cookie,并把Cookie返回给用户——>之后,在Cookie有效期内,该用户都携带Cookie
Cookie实则是key-value对,其中有个key是session-id,服务端根据Cookie中的session-id来唯一标识用户的专属数据
(2)Session角度——通过Session-id找到唯一对应的一组客户数据
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YW4jI4CR-1657073870551)(C:\Users\星\AppData\Roaming\Typora\typora-user-images\1655772468649.png)]](https://1000bd.com/contentImg/2022/07/06/155131762.png)
服务端这边使用Session来记录Cookie及其对应着的用户信息,每一个用户对应的session-id都是唯一的,服务端将session-id发给用户后,用户每一个连接都需要携带session-id,比如携带在Cookie中
(3)二者相互配合
所以,Cookie是身份凭证,是客户端的机制,而Session则是服务端的机制,一般,将Session-id发给客户端后,客户端将其携带在Cookie中,二者相互配合,以达到会话管理的目的
Servlet 的 Session 默认是保存在内存中的. 如果重启服务器则 Session 数据就会丢失.
第一次访问,需要办理Cookie,然后准备专属的数据柜(Session)
req.getSession(true);
// true的含义:如果是会员,则返回之前的柜子,如果不是会员,则新建一个新柜子
// fals的含义:不创建会员
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Date;
/**Cookie-Session机制
* @author sunny
* @date 2022/06/16 19:52
**/
@WebServlet("/firstVisited")
public class FirseVisit extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 第一次访问,需要办理会员卡
// true的含义:如果是会员,则返回之前的柜子,如果不是会员,则新建一个新柜子
HttpSession session = req.getSession(true);
session.setAttribute("first_visit",new Date());
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/plain");
resp.getWriter().println("办理会员成功");
}
}
观察可以看到:
第一次访问时:响应头中有个 Set-Cookie
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RCbmAj2i-1657073870553)(C:\Users\星\AppData\Roaming\Typora\typora-user-images\1655773534025.png)]](https://1000bd.com/contentImg/2022/07/06/155132040.png)
再次访问,请求头中开始携带Cookie
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bPlVcVh8-1657073870553)(C:\Users\星\AppData\Roaming\Typora\typora-user-images\1655773318431.png)]](https://1000bd.com/contentImg/2022/07/06/155132410.png)
(1)Session结构
Session结构:Map<key,value>
其中key值是session-id,value值就是HttpSession对象(每个客户专属的数据柜,value内部又是name-value键值对,比如name:xxx,age:13)
(2)HttpSession对象的常见方法
HttpSession session = req.getSession(true);
// 根据name获取value,如果没有则返回null
session.getAttribute("name");
session.setAttribute("first_visit",new Date());
//插入或者更新name-value
// 根据name删除键值对
session.removeAttribute("name");
(3)Session默认存储在内存中(重新运行进程就没了)
Servlet 的 Session 默认是保存在内存中的. 如果重启服务器则 Session 数据就会丢失.
Tomcat也支持其他持久化存储,比如存在本地文件,数据库里
不同浏览器视为不同的用户~
(3)小栗子:
/firstVisited——第一次访问,创建Cookie,增加了键值对-first_visit-new Date()
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Date;
/**Cookie-Session机制
* @author sunny
* @date 2022/06/16 19:52
**/
@WebServlet("/firstVisited")
public class FirseVisit extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 第一次访问,需要办理会员卡
// true的含义:如果是会员,则返回之前的柜子,如果不是会员,则新建一个新柜子
HttpSession session = req.getSession(true);
// session.getAttribute("name");
session.setAttribute("first_visit",new Date());
根据name删除键值对
// session.removeAttribute("name");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/plain");
resp.getWriter().println("办理会员成功");
}
}
/getfirstTime——查看是否获得Cookie,并返回首次获得的时间
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
/**
* @author sunny
* @date 2022/06/16 20:35
**/
@WebServlet("/getfirstTime")
public class GetFirstTime extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/plain");
PrintWriter writer = resp.getWriter();
HttpSession session = req.getSession(false);
if(session == null){
writer.println("没有Session,说明还没有办理Cookie,不是会员");
return;
}
Object o = session.getAttribute("first_visit");
if(o == null){
writer.println("文件柜有,但value为空,没有内容");
return;
}
Date date = (Date) o;
writer.println(date);
}
}
现象:
直接访问 localhost:8080/getfirstTime
因为并没有获得Cookie,所以

先访问 localhost:8080/firstVisited ,办理会员

再访问 localhost:8080/getfirstTime ,得到时间

那么,什么时候会打印“文件柜有,但value为空,没有内容”这句话呢?
当我们把get中的办理会员的false改为true,然后直接访问get,就可以得到这句话,因为办理了但并没有插入键值对,所以是Null

两者虽然常见都是配合使用,但其实均可独立使用
(1)Cookie的单独使用
Cookie是凭证,在请求头或者响应头中体现为Cookie,SetCookie
只设置Cookie,还可以设置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;
/**
* @author sunny
* @date 2022/06/16 20:53
**/
@WebServlet("/onlysetcookie")
public class OnlySetCookieServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Cookie cookie = new Cookie("name","yiyi");
// 设置Cookie的域名范围
// cookie.setDomain();//比如设置成“qq.com”,凡是什么什么qq.com的都可以
// 设置Cookie的最大会话时间
cookie.setMaxAge(120);
// 设置Cookie的路径范围
cookie.setPath("/");
resp.addCookie(cookie);
Cookie cookie1 = new Cookie("key","value");
resp.addCookie(cookie1);
}
}
只获取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;
/**
* @author sunny
* @date 2022/06/16 20:59
**/
@WebServlet("/onlygetcookie")
public class OnlyGetCookieServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Cookie[] cookies = req.getCookies();
for(Cookie cookie : cookies){
System.out.println(cookie.getName() + "——》" + cookie.getValue());
}
}
}
设置Cookie的最大会话时间,默认是浏览器关闭就没了

关闭浏览器后,再重新访问别的页面,可以发现,会话那个已经消失;了

(2)Session的单独使用
比如可以将session-id直接携带在url中等
Cookie+Session最主要的是用作登录态管理的,判断用户是否登录,获取当前用户等。