无状态HTTP的“记忆”方案:Spring Boot中CookieSession全栈实战
🔍 开发者资源导航 🔍 |
---|
🏷️ 博客主页: 个人主页 |
📚 专栏订阅: JavaEE全栈专栏 |
1. 什么是Cookie/Session?
http是无状态的,没有记忆力的,本次的通信和下次的通信是没有关联的,而在实际开发中是需要联系的。
那么能想到什么方法来解决它呢?存储!将信息存储起来建立关联。
但是网页是不被允许访问本地文件的,因此我们没办法将信息以文件的形式存储在本地。
我们只能将信息存储在服务器上面,而这些信息又被称之为“会话”,也就是Session。
我们的存储问题得到了解决,但是这样又会出现一个新的问题,如何将让客户端找到自己的Session呢?
Cookie就是两者关联的关键机制,Cookie是一种被允许存储在浏览器本身上的一种信息,当访问服务端时,Cookie会被一并带过去,这样服务端就能根据Cookie找到之前的会话状态。
一个典型的例子就是:
- 当我们在一个网站上登录以后,之后的很长时间都不需要再次登录。
在浏览器中,我们点击F12可以直接查看到Cookie的存储信息:
2. 获取/设置Cookie
2.1传统方式
HttpServerletRequest和HttpServletResponse 是serverlet里面的东西,可以用来接受请求/响应,可以使用该类获取到请求/响应中的关键信息,在使用时,它的位置可以随意放 spring在看到它的时候会自动传给他。
设置Cookie:
@GetMapping("/set-cookie")public String setCookie(HttpServletResponse response) {// 创建一个Cookie,名称为 "username",值为 "JohnDoe"Cookie cookie = new Cookie("username", "JohnDoe");// 设置Cookie的有效期(单位:秒),例如1小时cookie.setMaxAge(60 * 60);// 可选:设置Cookie的路径,通常设为 "/" 表示整个应用可用cookie.setPath("/");// 可选:设置是否仅通过HTTPS传输// cookie.setSecure(true);// 可选:设置是否仅通过HTTP访问,防止JavaScript访问(增强安全性)// cookie.setHttpOnly(true);// 将Cookie添加到响应中response.addCookie(cookie);return "cookie-set-success"; // 返回视图名称}
此时我们可以从浏览器中看到设置Cookie成功了。
注意:cookie的key值只能存在一个,如果设置的Cookie已经存在会覆盖掉旧的Cookie值。
获取Cookie:
@RequestMapping("/cookies")public String cookies(HttpServletRequest request) {Cookie[] cookies = request.getCookies();if (cookies != null) {for (Cookie cookie : cookies) {System.out.println(cookie.getName() + ":" + cookie.getValue());}}return "yes";}
此时的结果会在编译器的终端上打印出来:
2.2 注解方式
@CookieValue可以获取到指定名称的Cookie值,但是缺点是只能获取到单一值,因此并不常用。
@RequestMapping("/cookies1")public String cookies1(@CookieValue("username") String name) {return "username:" + name;}
结果:
3. 获取/设置Session
3.1 传统方式
Cookie和Session的连接通过一个sessionId的Cookie值来进行传递的,服务器会使用哈希表来自动保存和设置他们两者之间的映射关系,方便之后的查询。
设置Session:
getSession()内部参数可以传入一个布尔值,默认为ture
如果为true,没有获取到session时,自动创建并返回一个空的Session对象。
如果为false,没有获取到session时,返回null。
@RequestMapping("/setsession")public String setSession(HttpServletRequest request) {//根据cookie自动去获取sessionid,再根据sessionid去获取session对象,//因为默认是true,所以如果没有找到id会创建一个新的session//session是存储在内存里面的HttpSession session = request.getSession();//可以设置为参数,这样就是动态的了session.setAttribute("name","lyf");session.setAttribute("age",90);return "设置成功";}
此处我们运行成功后就多了一个Cookie值,它的作用就是用于连接服务器的会话状态,它的设置是自动的,并不需要我们手动进行。
我们也可以简化一下获取Session的方式,直接使用HttpSession作为传参类型,通过这样的方式获取相当于使用getSession方法传入了一个true的值,不存在时自动创建一个空的Session。
@RequestMapping("/setsession")public String setSession(HttpSession session) {session.setAttribute("name","lyf");session.setAttribute("age",90);return "设置成功";}
获取Session值:
@RequestMapping("/getsession")public String getSession(HttpServletRequest request) {//也是根据cookie去获取session,如果没找到这个session说明没有使用过setsession//也就没有session,可以认为没有登陆过HttpSession session = request.getSession(false);if (session == null) {return "no design infomation";}String name = (String)session.getAttribute("name");return "name:" + name;}
结果:
3.2 注解方式
通过@SessionAttribute注解直接获取当前会话的值,传入的参数是key值。
@RequestMapping("/getsession1")public String getSession1(@SessionAttribute("name") String name) {return "name:" + name;}