• JavaEE——Session会话追踪的实现机制


    引言

    HTTP协议是一个无状态协议,即Web应用程序无法区分收到的两个HTTP请求是否是同一个浏览器发出的。例如:当一个用户登录成功后,如果他继续请求访问其他页面、当一个用户在操作自己的购物车时,请求添加购物车然后结账。如果Web程序如何不能区分请求是否为同一用户的,就会导致混乱,因此在Web应用程序中,我们经常要跟踪用户身份。

    为了跟踪用户状态,服务器可以向浏览器分配一个唯一ID——Session ID,并以Cookie的形式发送到浏览器,浏览器在后续访问时总是附带此Cookie,这样,服务器就可以通过Cookie中的SessionID识别用户身份。

    Session

    我们把这种基于唯一ID识别用户身份的机制称为Session。每个用户第一次访问服务器后,会自动获得一个Session ID。如果用户在一段时间内没有访问服务器,那么Session会自动失效,下次即使带着上次分配的Session ID访问,服务器也认为这是一个新用户,会分配新的Session ID。一次Session会话中往往包含着若干次request请求。也就是同一个Session对象才能实现数据共享。

    Session在什么时候被创建

    1. package com.ywh.web.sevlet;
    2. import java.io.IOException;
    3. import javax.servlet.ServletContext;
    4. import javax.servlet.ServletException;
    5. import javax.servlet.annotation.WebServlet;
    6. import javax.servlet.http.Cookie;
    7. import javax.servlet.http.HttpServlet;
    8. import javax.servlet.http.HttpServletRequest;
    9. import javax.servlet.http.HttpServletResponse;
    10. import javax.servlet.http.HttpSession;
    11. @WebServlet("/test.do")
    12. public class TestSessionServlet extends HttpServlet {
    13. @Override
    14. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    15. System.out.println("TestSessionServlet被请求到!");
    16. }
    17. }

     

    启动服务器,在客户端发起请求后,虽然服务器收到请求,并做出了响应。但在浏览器里却并没有看到我们想看到的Cookie——JSESSIONID。即Session没有被创建出来。JavaEEServlet机制内建了对Session的支持。当我们需要获取Session时,可以通过request请求对象的getSession()方法。获取Session后,浏览器就会知道我们将会开启会话,这个时候服务器才会把SessionID以Cookie的形式响应给客户端:

    1. package com.ywh.web.sevlet;
    2. import java.io.IOException;
    3. import javax.servlet.ServletContext;
    4. import javax.servlet.ServletException;
    5. import javax.servlet.annotation.WebServlet;
    6. import javax.servlet.http.Cookie;
    7. import javax.servlet.http.HttpServlet;
    8. import javax.servlet.http.HttpServletRequest;
    9. import javax.servlet.http.HttpServletResponse;
    10. import javax.servlet.http.HttpSession;
    11. @WebServlet("/test.do")
    12. public class TestSessionServlet extends HttpServlet {
    13. @Override
    14. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    15. System.out.println("TestSessionServlet被请求到!");
    16. HttpSession session = req.getSession();
    17. System.out.println(session.getId());
    18. //创建Cookie
    19. Cookie cookie1 = new Cookie("phone_number1", "18799998888");
    20. Cookie cookie2 = new Cookie("phone_number2", "18799991111");
    21. Cookie cookie3 = new Cookie("phone_number3", "18799992222");
    22. Cookie cookie4 = new Cookie("phone_number4", "18799993333");
    23. Cookie cookie5 = new Cookie("phone_number5", "18799994444");
    24. //设置Cookie的时间
    25. //cookie.setMasAge();单位是秒
    26. //把Cookie存入
    27. resp.addCookie(cookie1);
    28. resp.addCookie(cookie2);
    29. resp.addCookie(cookie3);
    30. resp.addCookie(cookie4);
    31. resp.addCookie(cookie5);
    32. }
    33. }

     我们也可以在程序中自己创建出Cookie对象,然后响应给浏览器(客户端)

     服务器识别Session的关键就是依靠一个名为JSESSIONIDCookie。在Servlet中第一次调用req.getSession()时,Servlet容器自动创建一个Session ID,然后通过一个名为JSESSIONIDCookie发送给浏览器:

    获取HttpSession后,常见的操作方法有:

    • void setAttribute(String name, Object value):将指定Key-Value键值对,存入当前Session会话中。
    • Object getAttribute(String name):按照指定的Key从当前Session会话中获取Value,返回值为Object类型的对象,如果不存在,则返回null
    • void removeAttribute(String name):按照指定的Key从当前Session会话中删除Key-Value键值对。
    • long getCreationTime():获取当前Session会话的创建时间。
    • long getLastAccessedTime():获取当前Session会话最后一次请求的访问时间。
    • String getId():获取当前Session会话的SESSION ID

    使用Session时,由于服务器把所有用户的Session都存储在内存中,如果遇到内存不足的情况,就需要把部分不活动的Session序列化到磁盘上,这会大大降低服务器的运行效率,因此,放入Session的数据不能太大,否则会影响服务器的运行。

    Session何时失效
    1.服务器关闭或服务停止。

    2.程序调用HttpSession.invalidate()。

    3.Session超时:超时指的是连续一定时间服务器没有收到该Session所对应客户端的请求,并且这个时间超过了服务器设置的Session超时的最大时间。
     

    Cookie

    实际上,Servlet提供的HttpSession本质上就是通过一个名为JSESSIONIDCookie来跟踪用户会话的。除了这个名称外,其他名称的Cookie我们可以任意使用。

    创建一个新Cookie时,除了指定名称和值以外,通常需要设置setPath("/"),浏览器根据此前缀决定是否发送Cookie。如果一个Cookie调用了setPath("/user/"),那么浏览器只有在请求以/user/开头的路径时才会附加此Cookie。通过setMaxAge()设置Cookie的有效期,单位为秒,最后通过resp.addCookie()把它添加到响应。

    通过创建Cookie,我们可以实现在客户端浏览器中存储数据的目的,例如保存用户名和密码。在Chrome浏览器中,单个 Cookie的长度不能超过 4069 个字符(包括 name,但不包括 = 号)。

    读取Cookie

    1. package com.ywh.web.sevlet;
    2. import java.io.IOException;
    3. import javax.servlet.ServletException;
    4. import javax.servlet.annotation.WebServlet;
    5. import javax.servlet.http.Cookie;
    6. import javax.servlet.http.HttpServlet;
    7. import javax.servlet.http.HttpServletRequest;
    8. import javax.servlet.http.HttpServletResponse;
    9. @WebServlet("/test_cookie.do")
    10. public class Test_cookie extends HttpServlet {
    11. @Override
    12. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    13. Cookie[] cookies = req.getCookies();
    14. if (cookies != null) {
    15. for (Cookie ck : cookies) {
    16. System.out.println(ck.getName());
    17. System.out.println(ck.getValue());
    18. }
    19. }
    20. }
    21. }

     读取Cookie要通过HttpServletRequest 对象req调用getCookies()方法,此方法返回用户请求中附带的所有Cookie。

    总结

    Servlet容器提供了Session机制以跟踪用户;

    Session数据存储在服务器端,Cookie数据存储在客户端;

    默认的Session机制是以Cookie形式实现的,Cookie名称是JSESSIONID;它是服务器识别Session的关键;

  • 相关阅读:
    MATLAB向量
    设计模式:责任链模式
    python 在window对exe、注册表、bat、系统服务操作等实例讲解
    Linux环境下的Java(JDBC)连接openGauss数据库实践
    使用VScode SSH公网远程连接本地服务器开发【无公网IP内网穿透】
    亚马逊云科技数据分析为这伴科技赋能,实现“零”中断目标
    Reactive UI -- 反应式编程UI框架入门学习(一)
    【算法|双指针系列No.4】leetcode11. 盛最多水的容器
    每周一篇论文-规划算法Jump Point Search-Online Graph Pruning for Pathfinding on Grid Maps
    双软企业认证与税收优惠政策讲解(比较齐全)
  • 原文地址:https://blog.csdn.net/m0_59340907/article/details/126509634