• 会话管理——Cookie和 Session



    【前言】默认HTTP的请求是无状态的(无状态就是默认情况下 HTTP 协议的客户端和服务器之间的这次通信, 和下次通信之间没有直接的联系. 就是我可以会话,但不知道在和谁会话)

    谁在跟http会话,该跟谁会话了——Cookie + Session机制

    • Cookie是请求会话的身份凭证,是标识对象的凭证
    • Session是纯后台的数据,记录Cookie(身份凭证信息)及其对应着的用户信息

    基本原理

    (1)Cookie角度

    Cookie是浏览器-服务器之间的:

    ​ 浏览器需要保存Cookie,在合适的请求中携带Cookie,表现为HTTP请求头中的Cookie Header

    ​ 服务器生成Cookie并传递给浏览器,表现为响应头中的set Cookie

    用户第一次登录——>服务端为该用户生成一个Cookie,并把Cookie返回给用户——>之后,在Cookie有效期内,该用户都携带Cookie

    Cookie实则是key-value对,其中有个key是session-id,服务端根据Cookie中的session-id来唯一标识用户的专属数据

    (2)Session角度——通过Session-id找到唯一对应的一组客户数据

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YW4jI4CR-1657073870551)(C:\Users\星\AppData\Roaming\Typora\typora-user-images\1655772468649.png)]

    服务端这边使用Session来记录Cookie及其对应着的用户信息,每一个用户对应的session-id都是唯一的,服务端将session-id发给用户后,用户每一个连接都需要携带session-id,比如携带在Cookie中

    (3)二者相互配合

    所以,Cookie是身份凭证,是客户端的机制,而Session则是服务端的机制,一般,将Session-id发给客户端后,客户端将其携带在Cookie中,二者相互配合,以达到会话管理的目的

    Servlet 的 Session 默认是保存在内存中的. 如果重启服务器则 Session 数据就会丢失.

    Cookie

    第一次访问,需要办理Cookie,然后准备专属的数据柜(Session)

    req.getSession(true);

    //        true的含义:如果是会员,则返回之前的柜子,如果不是会员,则新建一个新柜子
    //		fals的含义:不创建会员
    
    • 1
    • 2
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    import java.io.IOException;
    import java.util.Date;
    
    /**Cookie-Session机制
     * @author sunny
     * @date 2022/06/16 19:52
     **/
    @WebServlet("/firstVisited")
    public class FirseVisit extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //        第一次访问,需要办理会员卡
    //        true的含义:如果是会员,则返回之前的柜子,如果不是会员,则新建一个新柜子
            HttpSession session = req.getSession(true);
            session.setAttribute("first_visit",new Date());
    
            resp.setCharacterEncoding("utf-8");
            resp.setContentType("text/plain");
            resp.getWriter().println("办理会员成功");
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    观察可以看到:

    第一次访问时:响应头中有个 Set-Cookie

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RCbmAj2i-1657073870553)(C:\Users\星\AppData\Roaming\Typora\typora-user-images\1655773534025.png)]

    再次访问,请求头中开始携带Cookie

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bPlVcVh8-1657073870553)(C:\Users\星\AppData\Roaming\Typora\typora-user-images\1655773318431.png)]

    Session(会话)

    (1)Session结构

    Session结构:Map<key,value>

    其中key值是session-id,value值就是HttpSession对象(每个客户专属的数据柜,value内部又是name-value键值对,比如name:xxx,age:13)

    (2)HttpSession对象的常见方法

    •     HttpSession session = req.getSession(true);
          // 根据name获取value,如果没有则返回null
          session.getAttribute("name");
      
      • 1
      • 2
      • 3
    •     session.setAttribute("first_visit",new Date());
          //插入或者更新name-value
      
      • 1
      • 2
    • //        根据name删除键值对
              session.removeAttribute("name");
      
      • 1
      • 2

    (3)Session默认存储在内存中(重新运行进程就没了)

    Servlet 的 Session 默认是保存在内存中的. 如果重启服务器则 Session 数据就会丢失.

    Tomcat也支持其他持久化存储,比如存在本地文件,数据库里

    不同浏览器视为不同的用户~

    (3)小栗子:

    /firstVisited——第一次访问,创建Cookie,增加了键值对-first_visit-new Date()

    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    import java.io.IOException;
    import java.util.Date;
    
    /**Cookie-Session机制
     * @author sunny
     * @date 2022/06/16 19:52
     **/
    @WebServlet("/firstVisited")
    public class FirseVisit extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //        第一次访问,需要办理会员卡
    //        true的含义:如果是会员,则返回之前的柜子,如果不是会员,则新建一个新柜子
            HttpSession session = req.getSession(true);
    //        session.getAttribute("name");
            session.setAttribute("first_visit",new Date());
            根据name删除键值对
    //        session.removeAttribute("name");
            resp.setCharacterEncoding("utf-8");
            resp.setContentType("text/plain");
            resp.getWriter().println("办理会员成功");
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    /getfirstTime——查看是否获得Cookie,并返回首次获得的时间

    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.Date;
    
    /**
     * @author sunny
     * @date 2022/06/16 20:35
     **/
    @WebServlet("/getfirstTime")
    public class GetFirstTime extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            resp.setCharacterEncoding("utf-8");
            resp.setContentType("text/plain");
            PrintWriter writer = resp.getWriter();
    
            HttpSession session = req.getSession(false);
            if(session == null){
                writer.println("没有Session,说明还没有办理Cookie,不是会员");
                return;
            }
    
            Object o = session.getAttribute("first_visit");
            if(o == null){
                writer.println("文件柜有,但value为空,没有内容");
                return;
            }
            Date date = (Date) o;
            writer.println(date);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    现象:

    直接访问 localhost:8080/getfirstTime

    因为并没有获得Cookie,所以
    在这里插入图片描述

    先访问 localhost:8080/firstVisited ,办理会员
    在这里插入图片描述

    再访问 localhost:8080/getfirstTime ,得到时间

    在这里插入图片描述

    那么,什么时候会打印“文件柜有,但value为空,没有内容”这句话呢?

    当我们把get中的办理会员的false改为true,然后直接访问get,就可以得到这句话,因为办理了但并没有插入键值对,所以是Null

    在这里插入图片描述

    Cookie VS Session

    两者虽然常见都是配合使用,但其实均可独立使用

    (1)Cookie的单独使用

    Cookie是凭证,在请求头或者响应头中体现为Cookie,SetCookie

    只设置Cookie,还可以设置Cookie的最大会话时间,

    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    /**
     * @author sunny
     * @date 2022/06/16 20:53
     **/
    @WebServlet("/onlysetcookie")
    public class OnlySetCookieServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            Cookie cookie = new Cookie("name","yiyi");
    //        设置Cookie的域名范围
    //        cookie.setDomain();//比如设置成“qq.com”,凡是什么什么qq.com的都可以
    //        设置Cookie的最大会话时间
            cookie.setMaxAge(120);
    //        设置Cookie的路径范围
            cookie.setPath("/");
            resp.addCookie(cookie);
            Cookie cookie1 = new Cookie("key","value");
            resp.addCookie(cookie1);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    只获取Cookie

    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    /**
     * @author sunny
     * @date 2022/06/16 20:59
     **/
    @WebServlet("/onlygetcookie")
    public class OnlyGetCookieServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            Cookie[] cookies = req.getCookies();
            for(Cookie cookie : cookies){
                System.out.println(cookie.getName() + "——》" + cookie.getValue());
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    设置Cookie的最大会话时间,默认是浏览器关闭就没了

    在这里插入图片描述

    关闭浏览器后,再重新访问别的页面,可以发现,会话那个已经消失;了

    在这里插入图片描述
    (2)Session的单独使用
    比如可以将session-id直接携带在url中等

    Cookie+Session最主要的是用作登录态管理的,判断用户是否登录,获取当前用户等。

  • 相关阅读:
    JavaScript | Hello World?【三】
    小工具之视频抽帧
    第六章 Java newCachedThreadPool 示例
    基于网络爬虫的新闻实时监测分析可视化系统(Java+MySQL+Web+Eclipse)
    46.全排列
    go手写Redis(8)之数据库核心层及指令实现
    WPF添加动画过渡效果
    WPF绘制圆形调色盘
    【Vue】动态组件和异步组件
    Typora设置代码块Mac风格三个圆点
  • 原文地址:https://blog.csdn.net/m0_58652786/article/details/125634274