一、Cookie:
HTTP 协议⾃身是属于 “⽆状态” 协议。“⽆状态” 的含义指的是:默认情况下 HTTP 协议的客户端和服务器之间的这次通信和下次通信之间没有直接的联系。但是实际开发中, 我们很多时候是需要知道请求之间的关联关系的。
例如登陆⽹站成功后, 第⼆次访问的时候服务器就能知道该请求是否是已经登陆过了:
注意:虽然Cookie可以记录登录的信息,但是Cookie信息是存储在客服端的,且很容易就可以伪造出,此时在服务器这边就需要记录令牌信息, 以及令牌对应的⽤户信息, 这个就是 Session 机制所做的⼯作。
二、理解会话机制 (Session)
服务器同⼀时刻收到的请求是很多的, 服务器需要清除的区分清楚每个请求是从属于哪个⽤户, 就需要在服务器这边记录每个⽤户令牌以及⽤户的信息的对应关系。会话的本质就是⼀个 “哈希表”, 存储了⼀些键值对结构, key 就是令牌的ID(token/sessionId), value 就是⽤户信息(⽤户信息可以根据需求灵活设计)。
●当⽤户登陆的时候, 服务器在 Session 中新增⼀个新记录, 并把 sessionId / token 返回给客户端. (例如通过 HTTP 响应中的 Set-Cookie 字段返回).
●客户端后续再给服务器发送请求的时候, 需要在请求中带上 sessionId/ token. (例如通过 HTTP 请求中的 Cookie 字段带上).
●服务器收到请求之后, 根据请求中的 sessionId / token 在 Session 信息中获取到对应的⽤户信息, 再进⾏后续操作。
注意:Servlet 的 Session 默认是保存在内存中的. 如果重启服务器则 Session 数据就会丢失.
三、Cookie和Session的区别
●Cookie 是客户端的机制,Session 是服务器端的机制。
●Cookie 和 Session 经常会在⼀起配合使⽤,但是不是必须配合。
a.完全可以⽤ Cookie 来保存⼀些数据在客户端, 这些数据不⼀定是⽤户身份信息,也不⼀定是token / sessionId。
b. Session 中的 token / sessionId 也不需要⾮得通过 Cookie / Set-Cookie 传递。
四、核心方法
HttpSession 类中的相关⽅法: 一个HttpSession 对象⾥⾯包含多个键值对,我们可以往 HttpSession 中存任何我们需要的信息。
**Cookie 类中的相关⽅法:**每个 Cookie 对象就是⼀个键值对。
●HTTP 的 Cookie 字段中存储的实际上是多组键值对,每个键值对在 Servlet 中都对应了⼀个 Cookie对象。
●通过 HttpServletRequest.getCookies() 获取到请求中的⼀系列 Cookie 键值对。
●通过 HttpServletResponse.addCookie() 可以向响应中添加新的 Cookie 键值对。
五、读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;
import java.time.LocalTime;
@WebServlet("/cookie")
public class CookieServlet extends HttpServlet {
/**
* 写Cookie到客户端
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Cookie cookie=new Cookie("myCookie","Bite"+LocalTime.now());
resp.addCookie(cookie);
resp.setContentType("text/html;charset=utf-8");
resp.getWriter().write("cookie添加成功!");
}
/**
* Cookie 读取
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Cookie[] cookies= req.getCookies();
StringBuilder builder=new StringBuilder();
//打印Cookies里面的所有信息
if(cookies!=null&&cookies.length>0) {
for (Cookie item : cookies) {
builder.append(item.getName() + ":" + item.getValue() + "<br>");
}
}
resp.setContentType("text/html;charset=utf-8");
resp.getWriter().write(builder.toString());
}
}
用Postman模拟请求:
POST:
GET:
注意:Cookie信息是存储在客户端的,所以当我们重启都端服务时,信息不会丢失;但是当我们切换客户端时(比如:从一个浏览器到另一个浏览器),原先的Cookie就会丢失。
六、读Session和写Session
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;
@WebServlet("/session")
public class SessionServlet extends HttpServlet {
private static final String SESSION_USER_KEY="SESSION_USER_KEY";
/**
* 读Session
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
//1、得到Session false表示的是有会话返回session对象,没有会话返回null
//true:有会话返回session对象,没有会话创建一个会话。 (会话:是否登录 )
HttpSession session=req.getSession(false);
if (null==session){
//没有登录
resp.getWriter().write("抱歉,尚未登陆!");
}else {
//已经登录:打印用户信息
//2、从Session中得到关联的对象
User user= (User) session.getAttribute(SESSION_USER_KEY);
resp.getWriter().write("登录成功|"+user);
}
}
/**
* 写Session
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
String result="操作失败!";
//1、得到Session
HttpSession session=req.getSession(true);
if (null!=session){
//表示已经得到或创建了会话
//2、将用户对象存储到session中
User user=new User();
user.setName("admin");
user.setPassword("admin");
session.setAttribute(SESSION_USER_KEY,user);
result="Session 写入成功!";
}
resp.getWriter().write(result);
}
}
session.getAttribute()的作用:
1.得到所有的cookie
2.匹配你的token
3.根据value匹配映射对象
session.setAttribute()的作用:
1.生成token(sessionID)
2.token关联到用户对象
3.发送存储cookie信息到客户端(token)