无状态HTTP的“记忆”方案:Spring Boot中Cookie&Session全栈实战


🔍 开发者资源导航 🔍
🏷️ 博客主页个人主页
📚 专栏订阅JavaEE全栈专栏

1. 什么是Cookie/Session?

http是无状态的,没有记忆力的,本次的通信和下次的通信是没有关联的,而在实际开发中是需要联系的。

那么能想到什么方法来解决它呢?存储!将信息存储起来建立关联。

但是网页是不被允许访问本地文件的,因此我们没办法将信息以文件的形式存储在本地。

我们只能将信息存储在服务器上面,而这些信息又被称之为"会话",也就是Session。

我们的存储问题得到了解决,但是这样又会出现一个新的问题,如何将让客户端找到自己的Session呢?

Cookie就是两者关联的关键机制,Cookie是一种被允许存储在浏览器本身上的一种信息,当访问服务端时,Cookie会被一并带过去,这样服务端就能根据Cookie找到之前的会话状态。

一个典型的例子就是:

  • 当我们在一个网站上登录以后,之后的很长时间都不需要再次登录。

在浏览器中,我们点击F12可以直接查看到Cookie的存储信息:

2. 获取/设置Cookie

2.1传统方式

HttpServerletRequest和HttpServletResponse 是serverlet里面的东西,可以用来接受请求/响应,可以使用该类获取到请求/响应中的关键信息,在使用时,它的位置可以随意放 spring在看到它的时候会自动传给他。

设置Cookie:

java 复制代码
    @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:

java 复制代码
    @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值,但是缺点是只能获取到单一值,因此并不常用。

java 复制代码
    @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。

java 复制代码
    @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。

java 复制代码
    @RequestMapping("/setsession")
    public String setSession(HttpSession session) {
        session.setAttribute("name","lyf");
        session.setAttribute("age",90);
        return "设置成功";
    }

获取Session值:

java 复制代码
    @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值。

java 复制代码
    @RequestMapping("/getsession1")
    public String getSession1(@SessionAttribute("name") String name) {
        return "name:" + name;
    }
相关推荐
FFFfengZiz.3 小时前
HTTP相关
网络·网络协议·http
m0_480502643 小时前
Rust 登堂 之 Cell 和 RefCell(十二)
开发语言·后端·rust
LunarCod3 小时前
Onvif设备端项目框架介绍
后端·嵌入式·c/c++·wsdl·rv1126·onvif
编啊编程啊程3 小时前
gRPC从0到1系列【19】
java·spring boot·rpc·dubbo·nio
谢语花4 小时前
【VS2022】LNK assimp64.lib找不到文件_openframework
android·运维·服务器
马克学长4 小时前
SSM村务管理系统s2qnw(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
java·服务器·数据库
羊锦磊4 小时前
[ Spring 框架 ] 数据访问和事务管理
java·后端·spring
未来coding4 小时前
Spring Boot SSE 流式输出,智能体的实时响应
java·spring boot·后端
whltaoin4 小时前
Spring Boot自定义全局异常处理:从痛点到优雅实现
java·spring boot·后端