介绍 Cookie 与 Session
Session 类似哈希表,存储了一些键值对结构,Key 就是 SessionID,Vaule 就是用户信息,客户端发起会话的时候,服务器一旦接收,就会创建会话【也就是 Session】,通过 Session 保存客户端的信息,一般使用 Set-Cookie 来将 SessionID 存储在 客户端的 Cookie 中,然后客户端在接下来的请求就会带上这个 ID ,这样服务器就可以识别是哪个客户端发来的请求,做出相应的响应。
Cookie 存储在客户端上,Session 存储在服务端,一般我们通过 Set-Cookie ,将 SessionID 存储在 Cookie 中。
Cookie 和 Session 的区别:
1)Cookie 是客户端保存用户信息的一种机制,Session 是服务器端保存用户信息的一种机制
2)Cookie 和 Session 之间主要通过 SessionID 关联起来,SessionID 是 Cookie 和 Session 之间的桥梁
3)Cookie 和 Session 经常配合在一起使用,但不是一定要配合。例如:可以完全使用 Cookie 来保存一些数据在客户端上,这些数据不一定是用户的身份信息,也不一定是SessionID;Session 中的 sessionID 也不需要非得通过 Cookie / Set-Cookie 传递,比如通过 URL 传递。
http 是无状态的
无状态可以理解为服务器是没有记忆力的,由于服务器一般是和多台客户端进行交互的,因此服务器要想知道是哪一个客户端发来的请求,请求需要保存客户端的信息,这样服务器才能通过这些信息查询是哪个客户端,这些信息就是令牌【令牌除了包含 SessionID之外,还可以有其他用户信息】
客户端在发送请求的时候,需要带上这个令牌,这样服务器就认识这个哪个客户端了。
http 无状态是一个良好的设计,一般我们使用多个服务器对外提供服务,正因为 http 是无状态的【客户端就不需要绑定特定的服务器来进行交互】,所以即使其中一个服务器负荷了,这个客户端的请求也可以被其他服务器处理。
以登录为例子:
用户登录时,服务器会在 Session 中创建一个新的记录,并把 SessionID 返回给客户端,通过 HTTP 响应中的
Set-Cookie 字段返回
客户端后续再给服务器发送请求时,需要在请求中带上 SessionID,通过 HTTP 请求中的 Cookie 字段带上
服务器收到请求之后,根据请求中的 SessionID 在 Session 信息中获得对应的用户信息,再进行后续的操作,
如果找不到则重新创建 Session,并把 SessionID 返回
HttpServletRequest
SpringMVC 是基于 Servlet api 构建的原始 Web 框架,也是在 Servlet 的基础上实现的
HttpServletResquest 代表客户端的请求
Cookie
在 postman 如何设置 Cookie???
首先点击 Headers,设置 Cookie 就可以了。
@RequestMapping("/r5")
public String r5(HttpServletRequest request) {
Cookie[] cookies = request.getCookies();
if(cookies != null) {
for(Cookie c : cookies) {
System.out.println(c.getName() + ": " + c.getValue());
}
}
return "成功获取Cookie 信息";
}
@CookieValue(简易获取 Cookie)
@RequestMapping("/r6")
public String r6(@CookieValue("java") String java) {
return java;
}
设置 Cookie
Session
Session 是 服务器端的机制,我们需要先存储,才能再获取
Session 是基于 HttpServletRequest 存储和和获取的
存储和设置 Session
通过 HttpServletRequest 获取 Session ,本质上就是通过 SessionID 在服务端内找寻 Session,然后进行响应的设置。如果没有 SessionID 或者 没有找到对应 的 Session ,服务端就会创建 Session.
调用 setAttribute 方法来进行设置 Session 操作
@RequestMapping("/r9")
public String r9(HttpServletRequest request) {
HttpSession session = request.getSession();
session.setAttribute("userName","java");
session.setAttribute("age","20");
return "设置 Session 成功";
}
还可以直接通过 HttpSession 来进行获取:
@RequestMapping("/r10")
public String r10(HttpSession session) {
session.setAttribute("userName", "java");
session.setAttribute("age",20);
return "获取 Session 成功!";
}
下面的浏览器发送的请求:
下面是通过 postman 发送请求的数据包:
从上面的 Session ID 佐证了不同的客户端的 ID 是不同的。
当你使用 HttpServletRequest 的获取 Session (调用 getSession),如果没有获取到 Session,这个方法会默认让服务端创建 Session ,保证获取到 的 Session 不为 null.
如果你调用的是 getSession(false) 的话,如果查询不到 Session 是不会默认创建 Session 的
例如:客户端需要先登录才能进行下一步的操作,如果没有登录的话,就查询不到Session ,这时候要先提醒客户端先进行登录操作,然后等待用户填写完登录信息,我们才创建 Session,将 SessionID 设置到 Cookie
@RequestMapping("r11")
public String r11(HttpServletRequest request) {
HttpSession session = request.getSession(false);
if(session == null) {
return "请先登录";
}
return "开始下一步的操作";
}
获取 Session 内的数据
通过 getAttribute 来获取
@RequestMapping("/r12")
public String getSession(HttpSession session) {
return (String) session.getAttribute("userName");
}
通过 @SessionAttribute
@RequestMapping("/r13")
public String getSession2(@SessionAttribute("userName") String userName) {
return userName;
}
@RequestMapping("/r13")
public String getSession2(@SessionAttribute(value = "userName",required = false) String userName) {
return userName;
}
获取 Header
通过 HttpServletRequest
@RequestMapping("r14")
public String getHeader(HttpServletRequest request) {
String urerAgent = request.getHeader("User-Agent");
return "从 header 中获取 User-Agent:" + urerAgent;
}
通过 RequestHeader
@RequestMapping("r15")
public String r15(@RequestHeader("User-Agent") String userAgent) {
return "从 header 中获取 User-Agent:" + userAgent;
}
HttpServletResponse
HttpServeltResponse 代表 服务器的响应
我们可以通过 HttpServletResponse 来设置响应数据包。
设置状态码
调用 setStatus
@RequestMapping("r18")
public String r18(HttpServletResponse response) {
response.setStatus(500);
return "设置 http 状态码成功";
}
注意 状态码即使被你设置为 四百多或者 五百多,都不会影响到数据包的正常接收处理。
设置 Header
响应里也有 Header 部分,我们也可以进行相应的设置。
通过 setHeader 来设置,使用键值对方式,两个字符串分别对应键 和 值。
@RequestMapping("r19")
public String r19(HttpServletResponse response) {
response.setHeader("java","17");
response.setHeader("hello","world");
return "设置 response 的 header 成功";
}