背景
默认情况下HTTP请求是无状态的(可以对话,但是不知道在和谁对话,也就是 HTTP 协议的客户端和服务器之间的这次通信, 和下次通信之间没有直接的联系)。但是实际开发中, 我们很多时候是需要知道请求之间的关联关系的,为了知道在和谁对话,就有了 Cookies (相当于是一张会员卡,虽然我不知道你是谁,但是如果我看到了你携带的“会员卡”我就可以识别你的身份)和 Session (相当于是我的内部记忆,我在脑子里记得你的身份),登陆网站成功后, 第二次访问的时候服务器就能知道该请求是否是已经登陆过了
Cookie
图中的 "令牌" 通常就存储在 Cookie 字段中.
举个例子:
此时在服务器这边就需要记录令牌信息, 以及令牌对应的用户信息, 这个就是 Session 机制所做的工作.
下面我们来实现一下会员卡的办理
@WebServlet("/first-visit") public class FirstVisitServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //第一次访问,需要办会员卡(Cookie)+准备专属的文件(session) //这个session对象就是你的专属服务柜,会员卡已经隐含在里面了,只是我们看不到 HttpSession session = req.getSession(true); session.setAttribute("first-visit-at", new Date()); resp.setCharacterEncoding("utf-8"); resp.setContentType("text/plain"); resp.getWriter().println("办理会员成功"); } }
启动服务器后,访问一下127.0.0.1:8080/first-visit,我们就可以从开发人员工具网络面板里看到响应标头带有set-Cookie,
以及可以看到应用程序里就会保存此Cookie
当我们再次访问其他网站时请求头中就带有Cookie了
Session (理解会话机制 )

- 当用户登陆的时候, 服务器在 Session 中新增一个新记录, 并把 sessionId / token 返回给客户端.(例 如通过 HTTP 响应中的 Set-Cookie 字段返回).
- 客户端后续再给服务器发送请求的时候, 需要在请求中带上 sessionId/ token. (例如通过 HTTP 请求中的 Cookie 字段带上).
- 服务器收到请求之后, 根据请求中的 sessionId / token 在 Session 信息中获取到对应的用户信息,再进行后续操作.
Date date = (Date)o;
if(o == null){
(档案是有,但是没有存储创立时间)
}else{
(获取到了时间)
}
@WebServlet("/get-first-time") public class GetFirstTimeServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setCharacterEncoding("utf-8"); resp.setContentType("text/plain"); HttpSession session = req.getSession(false); if (session == null){ resp.getWriter().println("身份不符合"); return; }else { Object o = session.getAttribute("first-visit-at"); Date date = (Date) o; if (o == null){ resp.getWriter().println("无创建时间的记载"); return; }else { resp.getWriter().println(date); return; } } } }
此时我们要先去办理会员卡,否则服务器会找不到档案
会员卡办理成功
再次访问获取建立档案时间的页面,获取时间成功!
Cookie 和 Session 的区别
- Cookie 是客户端的机制. Session 是服务器端的机制.
- Cookie 和 Session 经常会在一起配合使用. 但是不是必须配合.
@WebServlet("/only-set-cookie") public class OnlySetCookie extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Cookie cookie1 = new Cookie("name", "jiaoer"); resp.addCookie(cookie1); Cookie cookie2 = new Cookie("age", "18"); resp.addCookie(cookie2); } }



若我们给Cookie设置过期时间,则name就会在到时间期限时消失,若我们不对过期时间进行设置,则过期时间就为此次会话,当进程结束Cookie就消失了。
@WebServlet("/only-get-cookie") public class OnlyGetCookie 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(); Cookie[] cookies = req.getCookies(); for (Cookie cookie : cookies) { System.out.println(cookie.getName() + "=" + cookie.getValue()); } } }

当然我们也可以在浏览器的应用里手动加入Cookie
再次进行访问,我们也可以获取到手动输入的Cookie
核心方法

HttpServletResponse 类中的相关方法

- HTTP 的 Cooke 字段中存储的实际上是多组键值对. 每个键值对在 Servlet 中都对应了一个 Cookie 对象.
- 通过 HttpServletRequest.getCookies() 获取到请求中的一系列 Cookie 键值对.
- 通过 HttpServletResponse.addCookie() 可以向响应中添加新的 Cookie 键值对