目录
一. HTTP无状态
HTTP协议是属于“无状态”的协议,即不保留关于请求状态的任何信息。
举一个简单的例子,当你用浏览器访问一个网站时,你可能会点击多个链接,浏览不同的页面。对于HTTP协议来说,每次你点击链接,浏览器都会向服务器发送一个新的请求。服务器在处理这个请求时,并不知道你之前浏览过哪些页面,它只关注当前这个请求。这就是所谓的“无状态”。
但是,实际应用中,我们通常需要服务器记住一些用户的信息,比如登录状态、购物车内容等。为了实现这个功能,我们通常会使用一些技术来在无状态的HTTP协议上模拟状态,比如使用Cookies、Session或者Token等。这些技术可以帮助服务器识别不同的用户,并在用户的多次请求之间保持某些状态信息。
二. Session与Cookie
Session (会话) 是服务器为了保存用户信息而创建的一个特殊的对象,这些信息通常用于跟踪和识别用户以及存储与用户相关的数据。
当一个未知的用户向Web应用程序发送第一个请求时,就开始了一个会话;当用户明确结束会话或服务器在一个时限内没有接受到用户的任何请求时,会话就结束了。对用户的每个请求,根据 Session ID,服务器能够识别出请求来自于同一个用户。
Session的本质就是一个"哈希表",存储了一些键值对结构。Key就是SessionlD,Value就是用户信息(用户信息可以根据需求灵活设计)
Cookie是服务器发送到浏览器的一小段信息。浏览器会存储这些信息,并在下次访问同一个网站时,把Cookie发送回服务器。这样,服务器就能记住你的登录状态、身份验证令牌或其他需要保存的信息。
工作原理:
- 当用户首次访问服务器时,服务器会创建一个Session,并在服务器内存中存储与该用户相关的信息
- 服务器会生成一个SessionID,当服务器发送响应给浏览器时,可以在响应头中包含一个Set-Cookie字段,浏览器会根据这个字段存储Cookie(浏览器会将Cookie保存在本地,通常是一个小文件)
- 当浏览器再次向同一个服务器发送请求时,它会自动在请求头中带上相应的Cookie
- 服务器通过SessionID找到对应的Session信息
Session特点:
- 存储在服务器端,因此不会被客户端直接访问。
- 可以存储比Cookie更多的数据,因为不受浏览器Cookie大小的限制。
- Session是基于内存的,服务器重启会导致Session丢失,除非采取了额外的持久化措施。
- 需要服务器来管理内存和生命周期
Cookie特点:
- 存储在客户端,因此可以被客户端的JavaScript访问和修改(除非设置为HttpOnly)
- 有大小限制,通常为4KB
- 可以设置过期时间,过期后Cookie会被浏览器删除
Cookie的创建:
1)清空浏览器中Cookie记录后,向www.baidu.com的网址发送请求,抓包后的结果:
2)再次访问时,请求中就会携带上Cookie字段:
通过F12,可以查看Cookie信息或者修改Cookie
Cookie和Session的区别:
- Cookie是客户端保存用户信息的一种机制;Session是服务器端保存用户信息的一种机制。
- Cookie和Session之间主要是通过Session ID关联起来的,Session ID是Cookie和Session之间的桥梁。
- Cookie和 Session经常会在一起配合使用,但是不是必须配合:
· 完全可以用Cookie来保存一些数据在客户端。这些数据不一定是用户身份信息,也不一定是 Session ID。
· Session中的 Session ID 也并非必须通过Cookie/Set-Cookie传递,也可通过URL传递。
三. 获取Cookie
3.1 传统获取Cookie
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RequestMapping;
@RequestMapping("/cookie")
@Controller
public class Cookie {
@RequestMapping("method")
public String method(HttpServletRequest request){
HttpSession session = request.getSession();
System.out.println(session.getId());
//获取所有cookie信息
jakarta.servlet.http.Cookie[] cookies = request.getCookies();
if(cookies != null){
//遍历cookie信息
StringBuilder cookieInfo = new StringBuilder();
for (jakarta.servlet.http.Cookie cookie : cookies) {
cookieInfo.append(cookie.getName()+":"+cookie.getValue()+" ");
}
return "Cookie信息: "+cookieInfo.toString();
}else{
return "Cookie信息为空";
}
}
}
SpringMVC是基于Servlet API构建的原始Web框架,也是在Servlet的基础上实现的
HttpServletRequest,HttpServletResponse 是Servlet提供的两个类,是Spring MVC方法的内置对象,需要时直接在方法中添加声明即可。Spring MVC在这两个对象的基础上进行了封装,给我们提供更加简单的使用方法。
- HttpServletRequest 对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中。通过这个对象提供的方法,可以获得客户端请求的所有信息。
- HttpServletResponse 对象代表服务器的响应,HTTP响应的信息都在这个对象中,如向客户端发送的数据,响应头,状态码等。通过这个对象提供的方法,可以获得服务器响应的所有内容。
3.2 简洁获取Cookie
@RequestMapping("cookie")
public String cookie(@CookieValue("cookie") String cookie){
return "Cookie信息: "+ cookie;
}
四. 获取Session
3.1 Session的存储与获取
Session是服务器端的机制,我们需要先存储,才能再获取。Session也是基于HttpServletRequest 来存储和获取的。
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@RequestMapping("/session")
@Controller
public class Session {
@RequestMapping("/set")
public String setSessionAttribute(HttpServletRequest request) {
HttpSession session = request.getSession();
//设置Session属性
session.setAttribute("username", "zhu");
return "session 存储成功";
}
@RequestMapping("/get")
public String getSessionAttribute(HttpServletRequest request) {
HttpSession session = request.getSession(false);
String username = null;
//可以根据Session中的信息,判断用户是否登录
if(session != null && session.getAttribute("username") != null){
username = (String)session.getAttribute("username");
}
return "username: "+ username;
}
}
代码中看不到Session ID这样的概念,因为getSession操作内部提取到请求中的Cookie里的Session ID,然后根据Session ID获取到对应的Session对象,Session对象用HttpSession来描述
HttpSession getSession(boolean create);
HttpSession getSession();
void setAttribute(String name,Object value);
Object getAttribute(String name);
- HttpSession getSession(boolean create):参数如果为 true,则当不存在会话时新建会话;参数如果为 false,则当不存在会话时返回 null
- HttpSession getSession():和 getSession(true) 含义一样,默认值为true
- void setAttribute(String name,Object value):使用指定的名称绑定一个对象到该 session 会话
- Object getAttribute(String name):返回在该session 会话中具有指定名称的对象,如果没有指定名称的对象,则返回null
3.2 简洁获取Session
通过 Spring MVC 内置对象HttpSession来获取
@RequestMapping("/get2")
public String session(HttpSession session) {
String username = (String)session.getAttribute("username");
return "username: "+ username;
}