一.Cookie
- 首先我们知道HTTP协议本身是''无状态''的, 这里的''无状态''指的是:默认情况下HTTP协议的客户端和服务器之间的这次通信,和下次通信之间没有直接的联系. 但是在实际的开发过程之中, 我们很多时候是需要知道请求之间的关联关系的. 例如登陆网站成功后,第二次访问的时候服务器就能知道该请求是否是已经登录过了. 换句话说,假设你刚从浏览器上登录了你的LeetCode账号,然后把该页面关掉,一段时间之内你再次进入时就不需要再次输入账号密码了
- 用图表示上述过程就是:
- 上述途中的''令牌''通常就存储在Cookie字段中.
- 举个例子:比如去医院挂号.
*- 看病之前先挂号, 挂号的时候需要提供身份证证件, 此时你就获得了一张"就诊卡", 这个就诊卡就相当于患者的"令牌". 此时医院的系统之中就会存储你的身份信息.
-
- 后续去各个科室进行检查诊断,开药等操作, 都不比在出示身份证件了, 只要有就诊卡即可识别出当前患者的身份了.
-
- 看完病之后, 不想要就诊卡了, 就可以注销这个卡, 此时患者的身份就和就诊卡的关联就销毁了, 医院之中的系统就不会再记录这个数据了, 再次拿这个卡去看病就会不起作用了 (类似于网站的注销操作).
-
- 如果下次再来看病, 就需要再办一张就诊卡, 此时就相当于又获得一一张''令牌''
- 举个例子:比如去医院挂号.
此时在服务器(医院)这边就需要记录"令牌"信息, 以及令牌对应的用户信息, 这个就是 Session 机制所做的工作.
二.Session
理解会话.
-
会话也是对话的意思.
-
在计算机领域, 会话是一个客户与服务器之间的不中断的请求响应. 对客户的每个请求,服务器能够识别出请求来自于同一个客户. 当一个未知的客户向Web应用程序发送第一个请求时就开始了一个会话. 当客户明确结束会话或服务器在一个时限内没有接受到客户的任何请求时,会话就结束了.
- 比如我们打客服电话. 每次打客服电话, 就是一个会话. 挂断电话, 会话就结束了
下次再打客服电话, 就又是一个新的会话. 如果我们长时间不说话, 没有新的请求, 会话也会结束.
- 比如我们打客服电话. 每次打客服电话, 就是一个会话. 挂断电话, 会话就结束了
-
服务器同⼀时刻收到的请求是很多的. 服务器需要清楚的区分每个请求是从属于哪个用户, 也就是属于哪个会话, 就需要在服务器这边记录每个会话以及与用户的信息的对应关系.Session是服务器为了保存用户信息而创建的一个特殊的对象.
- Session的本质就是⼀个 "哈希表", 存储了⼀些键值对结构. Key 就是SessionID, Value 就是用户信息(用户信息可以根据需求灵活设计).
SessionId
- ==SessionId 是由服务器生成的一个 "唯一性字符串", 从 Session 机制的角度来看, 这个唯一性字符串称为 "SessionId". 但是站在整个登录流程中看待, 也可以把这个唯一性字符串称为 "token". ==上述例子中的令牌ID, 就可以看做是SessionId, 只不过令牌除了ID之外, 还会带一些其他信息, 比如时间, 签名等.
SessionId是如何产生的
- 当用户登陆的时候, 服务器在 Session 中新增一个新记录, 并把 sessionId返回给客户端. (通过HTTP 响应中的 Set-Cookie 字段返回).
- 客户端后续再给服务器发送请求的时候, 需要在请求中带上 sessionId. (通过HTTP 请求中的Cookie 字段带上).
- 服务器收到请求之后, 根据请求中的 sessionId在 Session 信息中获取到对应的用户信息, 再进行后续操作.找不到则重新创建Session, 并把SessionId返回.
注:
Session 默认是保存在内存中的. 如果重启服务器则 Session 数据就会丢失.
三.Cookie 和 Session 的区别
- Cookie 是客户端保存用户信息的一种机制. Session 是服务器端保存用户信息的一种机制.
- Cookie 和 Session之间主要是通过 SessionId 关联起来的, SessionId 是 Cookie 和 Session 之间的桥梁
- Cookie 和 Session 经常会在一起配合使用. 但是不是必须配合.
- 完全可以用Cookie 来保存⼀些数据在客户端. 这些数据不一定是用户身份信息, 也不一定是SessionId.
- Session 中的sessionId 也不需要非得通过 Cookie/Set-Cookie 传递, 比如通过URL传递.
四.Cookie的存储和读取
方法一:传统的获取Cookie的方式.
java
@RequestMapping("/getCookie1")
public String getCookie(HttpServletRequest request, HttpServletResponse response) {
//获取参数
//String name = request.getParameter("name");
Cookie[] cookies = request.getCookies();
if (cookies != null) {
Arrays.stream(cookies).forEach(cookie -> {
System.out.println(cookie.getName()+":"+cookie.getValue());
});
}
return "获取cookie成功";
}
- Spring MVC是基于 Servlet API 构建的原始 Web 框架, 也是在Servlet的基础上实现的. HttpServletRequest , HttpServletResponse 是Servlet提供的两个类, 是Spring MVC方法的内置对象. 需要时直接在方法中添加声明即可.
- HttpServletRequest 对象代表客户端的请求, 当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,通过这个对象提供的方法,可以获得客户端请求的所有信息.
- HttpServletResponse 对象代表服务器的响应. HTTP响应的信息都在这个对象中, 比如向客户端发送的数据, 响应头, 状态码等. 通过这个对象提供的方法, 可以获得服务器响应的所有内容. Spring MVC在这两个对象的基础上进行了封装, 给我们提供更加简单的使用方法.
测试结果:
方法二:使用注解的方式获取Cookie.
java
@RequestMapping("/getCookie2")
public String getCookie2(@CookieValue("bite") String result){
return "获取到cookie值了,value:"+result;
}
五.Session的存储和读取
1.Session存储
java
@RequestMapping("/setSession")
public String setSession(HttpServletRequest request, HttpServletResponse response) {
//先从cookie中获取到sessionId,再根据sessionId获取session对象,如果没有获取到,就会自己创建一个session对象
HttpSession session = request.getSession();
session.setAttribute("name","zhangsan");
return "Session设置成功~~";
}
这个代码中看不到 SessionId 这样的概念的. getSession 操作内部提取到请求中的Cookie 里的SessionId, 然后根据SessionId获取到对应的Session 对象, Session 对象用HttpSession来描述
2.Session读取.
方法一
java
@RequestMapping("/getSession1")
public String getSession1(HttpServletRequest request, HttpServletResponse response) {
//先从cookie中获取到sessionId,再根据sessionId获取session对象
HttpSession session = request.getSession();
String name = (String)session.getAttribute("name");
return "获取到session的值了 name:"+name;
}
- 通过fiddler观察请求的详细情况:
可以看到, HTTP响应中, 通过Set-Cookie告知客⼾端, 把SessionID存储在Cookie中 - 通过浏览器, 可以观察到运行结果:
通过Fiddler观察Http请求和响应
可以看到, Http请求时, 把SessionId通过Cookie传递到了服务器
方法二:
java
@RequestMapping("/getSession2")
public String getSession2(HttpSession session, HttpServletResponse response) {
String name = (String)session.getAttribute("name");
return "获取到session的值了 name:"+name;
}
方法三:
java
@RequestMapping("/getSession3")
public String getSession3(@SessionAttribute("name") String name) {
//String name = (String)session.getAttribute("name");
return "获取到session的值了 name:"+name;
}
六.总结.
- Cookie 和Session都是会话机制, Cookie是客⼾端机制, Session是服务端机制. ⼆者通过SessionId来关联.
- Spring MVC内置HttpServletRequest, HttpServletResponse两个对象. 需要使用时, 直接在方法中添加对应参数即可, Cookie和Session可以从HttpServletRequest中来获取, 也可以直接使用HttpServletResponse设置HTTP响应状态码