当前位置: 首页 > news >正文

javaweb之会话管理

Cookie:

1. Cookie 的定义

  • Cookie 是存储在用户浏览器中的小块数据,通常由服务器发送并存储,以便在用户浏览器和服务器之间保持会话状态。
  • 每次用户发送请求时,浏览器都会自动附带相应的 Cookie,允许服务器辨识用户。

2. Cookie 的用途

  • 保持会话状态:用于存储用户登录状态或购物车等会话信息。
  • 个性化设置:保存用户的偏好设置,比如语言选择、字体大小等。
  • 跟踪用户行为:例如分析用户访问网站的行为,以进行个性化推荐。

3. Cookie 的分类

  • 会话 Cookie(Session Cookie):在浏览器关闭后失效,通常用于临时数据存储。
  • 持久 Cookie(Persistent Cookie):设置了过期时间,在过期前即使关闭浏览器也不会被删除。
默认情况下 Cookie 的有效期是一次会话范围内,我们可以通过 Cookie setMaxAge() 方法让 Cookie 持久化保存到浏览器上。
cookie.setMaxAge(int expiry) 参数单位是秒,表示 cookie 的持久化时间,如果设置参数为 0 ,表示将 浏览器中保存的该cookie 删除。

 session:

HttpSession的概述:

HttpSession是一种保留更多信息在服务端的一种技术 服务器会为每一个客户端开辟一块内存空
间,即session对象.。客户端在发送请求时,都可以使用自己的session。这样服务端就可以通过
session来记录某个客户端的状态了。

  • 服务端在为客户端创建session时,会同时将session对象的id,即JSESSIONIDCookie的形式放入响 应对象;  
  • 后端创建完session后,客户端会收到一个特殊的Cookie,叫做JSESSIONID
  • 客户端下一次请求时携带JSESSIONID,后端收到后,根据JSESSIONID找到对应的session对象;
  • 通过该机制,服务端通过session就可以存储一些专门针对某个客户端的信息了;
  • session也是域对象(后续详细讲解)

应用场景:

  1.  记录用户的登录状态: 用户登录后,将用户的账号等敏感信息存入session
  2.  记录用户操作的历史: 如记录用户的访问痕迹,用户的购物车信息等临时性的信息;

测试:  

注意!!!

生成web项目后,一定要删去index.jsp;原因:里面有内置的session对象,会干扰

 servlet1:

package servlet;import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;import java.io.IOException;
@WebServlet("/servlet1")
public class servlet1 extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 接收请求中的username参数String username = req.getParameter("username");// 获得session对象HttpSession session = req.getSession();// 改变session的失效时间session.setMaxInactiveInterval(120);System.out.println(session.getId());System.out.println(session.isNew());//判断请求中有没有一个特殊的cookie JSESSIONID 值*****//1有//根据 JSESSIONID找对应的session对象// 找到了// 返回之前的session// 没有找到// 创建一个新的session返回,并且向response对象中存放一个SESSIONID  的cookie// 2 没有// 创建一个新的session返回,并且向response对象中存放一个SESSIONID 的cookie// 将username存入sessionsession.setAttribute("username",username);// 客户端响应信息resp.setContentType("text/html;charset = UTF-8");resp.getWriter().write("成功");}
}

servlet2:

package servlet;import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;import java.io.IOException;
@WebServlet("/servlet1")
public class servlet1 extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 接收请求中的username参数String username = req.getParameter("username");// 获得session对象HttpSession session = req.getSession();// 改变session的失效时间session.setMaxInactiveInterval(120);System.out.println(session.getId());System.out.println(session.isNew());//判断请求中有没有一个特殊的cookie JSESSIONID 值*****//1有//根据 JSESSIONID找对应的session对象// 找到了// 返回之前的session// 没有找到// 创建一个新的session返回,并且向response对象中存放一个SESSIONID  的cookie// 2 没有// 创建一个新的session返回,并且向response对象中存放一个SESSIONID 的cookie// 将username存入sessionsession.setAttribute("username",username);// 客户端响应信息resp.setContentType("text/html;charset = UTF-8");resp.getWriter().write("成功");}
}

getSession方法的处理逻辑:

  • 初次请求

    • 浏览器向服务器发起第一次请求(请求报文)。
    • 服务器端处理该请求,创建一个新的Session,并将Session的ID(如JSESSIONID)保存在Cookie中,作为响应的一部分(响应报文),发送给浏览器。
  • 浏览器存储Cookie

    • 浏览器接收到服务器的响应,将Cookie中的JSESSIONID存储下来。
  • 再次请求

    • 当浏览器再次发起请求时,会自动携带之前存储的Cookie(包含JSESSIONID)。
    • 服务器接收到请求后,读取该Cookie中的Session ID(如JSESSIONID),找到与之对应的Session,获取其中存储的键值对数据,处理请求。
  • 响应返回

    • 服务器处理完请求后,再次返回响应报文,浏览器接收并继续进行后续的操作。

总结

  • 每次请求时,浏览器都会携带上次存储的Cookie来标识当前用户的会话。
  • 服务器通过读取Cookie中的JSESSIONID,找到对应的Session,进而保持会话数据的连续性。

 HttpSession时效性:

为什么要设置session的时效?

  • 用户量很大之后,Session对象相应的也要创建很多。如果一味创建不释放,那么服务器端的内存 迟早要被耗尽;
  • 客户端关闭行为无法被服务端直接侦测,或者客户端较长时间不操作也经常出现,类似这些的情 况,就需要对session的时限进行设置了(例如很久没登录过的哔哩哔哩要重新登录)
默认的 session 最大闲置时间 ( 两次使用同一个 session 中的间隔时间 ) Tomcat/conf/web.xml 配置为 30分钟。

 如何看TomCat里面设置的session时效呢?

 注意!!!!

这里不再是30s了,在Tomcat的配置文件中,<session-timeout> 的单位是分钟。因此,在图中设置的<session-timeout>30</session-timeout>表示Session超时时间为30分钟,服务器将自动使该Session失效。

如何自己设置时间?

我们可以自己在当前项目的web.xml对最大闲置时间进行重新设定。

也可以通过HttpSessionAPI 对最大闲置时间进行设定。 

三大域对象: 

域对象:一些用于存储数据和传递数据的对象。传递数据不同的范围,我们称之为不同的域。不
同的域对象代表不同的域,共享数据的范围也不同
web 项目中,我们一定要熟练使用的域对象分别是 :请求域、会话域、应用域;
  • 请求域对象是HttpServletRequest ,传递数据的范围是一次请求之内及请求转发;
  • 会话域对象是HttpSession,传递数据的范围是一次会话之内,可以跨多个请求;
  • 应用域对象是ServletContext,传递数据的范围是本应用之内,可以跨多个会话;

1. 请求域(Request Scope)

  • 对象: HttpServletRequest
  • 作用范围: 仅限于一次HTTP请求。在同一个请求过程中,数据可以在Servlet、JSP或其他组件之间共享。
获取不到数据的情况:
  • 请求已经结束: 请求域中的数据只在当前请求有效。一旦请求结束(如重定向、返回响应给客户端后),请求对象会销毁,数据将不可访问。(当然可以进行请求转发,可以获取数据)
  • 跨请求: 如果想在一次请求中设置数据,然后在下一次请求中获取(如重定向或从不同的页面发起请求),由于请求已经变化,无法获取之前的请求域数据。

2. 会话域(Session Scope)

  • 对象: HttpSession
  • 作用范围: 作用于一个用户会话期间。只要用户会话没有过期或销毁,数据可以在多个请求之间共享。
获取不到数据的情况:
  • Session过期或销毁: 如果用户长时间没有操作(超过了Session的超时时间,默认30分钟),Session会被服务器销毁,之后再尝试访问会话域中的数据将获取不到。
  • Session手动销毁: 通过调用session.invalidate(),会立即销毁会话,所有的会话域数据将被清除。
  • 新建Session: 如果在一个新的请求中,用户没有携带之前的Session(如关闭浏览器后再访问),服务器会创建一个新的Session,之前的会话域数据将获取不到。又比如两个浏览器不能共享数据,清空浏览器的历史记录

3. 应用域(Application Scope)

  • 对象: ServletContext
  • 作用范围: 作用于整个Web应用程序的生命周期。数据可以在整个应用程序范围内(跨用户和跨请求)共享,直到服务器停止或Web应用重新部署。
获取不到数据的情况:
  • 应用程序重启或重新部署: 服务器重启或Web应用重新部署时,应用域中的数据将会被销毁,再次访问时获取不到原有的数据。
  • 数据未设置: 如果程序没有显式地通过ServletContext设置数据,访问时自然获取不到。
  • 应用域数据手动移除: 如果调用removeAttribute()方法手动移除了某个数据项,也会导致后续无法获取该数据。

 测试 API:

servletA:

package servlet;import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;import java.io.IOException;@WebServlet("/servletA")
public class servletA extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 向请求域存放数据req.setAttribute("request","requestMessage");// 向会话域存放数据HttpSession session = req.getSession();session.setAttribute("session","sessionMessage");// 向应用域存放数据ServletContext servletContext = session.getServletContext();servletContext.setAttribute("application","applicationMessage");// 获取请求域String reqMse = (String) req.getAttribute("request");System.out.println("请求域" + reqMse);//        // 请求转发
//        req.getRequestDispatcher("/servletB").forward(req,resp);}}

servletB:

package servlet;import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;import java.io.IOException;
@WebServlet("/servletB")
public class servletB extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 获取请求域的数据String reqMse = (String) req.getAttribute("request");System.out.println("请求域" + reqMse);// 获取会话域的数据 换一个浏览器就获取不到数据了HttpSession session = req.getSession();String SessionMse = (String) session.getAttribute("session");System.out.println("会话域" + SessionMse);// 获取应用域的数据ServletContext servletContext =  session.getServletContext();String AppMse = (String) servletContext.getAttribute("application");System.out.println("应用域" + AppMse);}
}

相关文章:

  • 睡眠:生命的隐形守护者
  • 【Linux】防火墙
  • 前段辅助工具分享(像素大厨)
  • 网络编程操作—函数
  • Comfyui 学习笔记2
  • react:React Hook函数
  • 【iOS】计算器的仿写
  • 秦巴山区SHP格式矢量范围
  • OpenCV视频I/O(4)视频采集类VideoCapture之获取异常处理模式函数getExceptionMode()的使用
  • PHP的guzzlehttp/guzzle库在碰到各种异常时的场景
  • 【rust】 基于rust编写wasm,实现markdown转换为html文本
  • 智驭未来·电网负荷智控系统
  • <<迷雾>> 第 2 章 用电来表示数 示例电路
  • 700. 二叉搜索树中的搜索
  • 【JAVA】算法笔记
  • [rust! #004] [译] Rust 的内置 Traits, 使用场景, 方式, 和原因
  • CSS相对定位
  • JDK9: 集成 Jshell 和 Maven 项目.
  • niucms就是以城市为分割单位,在上面 小区/乡村/同城论坛+58+团购
  • python学习笔记 - ThreadLocal
  • sessionStorage和localStorage
  • vue从创建到完整的饿了么(11)组件的使用(svg图标及watch的简单使用)
  • vue学习系列(二)vue-cli
  • 多线程事务回滚
  • 将 Measurements 和 Units 应用到物理学
  • 开源中国专访:Chameleon原理首发,其它跨多端统一框架都是假的?
  • 让你的分享飞起来——极光推出社会化分享组件
  • 如何合理的规划jvm性能调优
  • 软件开发学习的5大技巧,你知道吗?
  • 小程序测试方案初探
  • 一个JAVA程序员成长之路分享
  • 用jquery写贪吃蛇
  • d²y/dx²; 偏导数问题 请问f1 f2是什么意思
  • 函数计算新功能-----支持C#函数
  • ​LeetCode解法汇总2182. 构造限制重复的字符串
  • # Apache SeaTunnel 究竟是什么?
  • #include<初见C语言之指针(5)>
  • $Django python中使用redis, django中使用(封装了),redis开启事务(管道)
  • (13)Hive调优——动态分区导致的小文件问题
  • (超简单)使用vuepress搭建自己的博客并部署到github pages上
  • (带教程)商业版SEO关键词按天计费系统:关键词排名优化、代理服务、手机自适应及搭建教程
  • (附源码)ssm高校社团管理系统 毕业设计 234162
  • (附源码)计算机毕业设计SSM智慧停车系统
  • (三)SvelteKit教程:layout 文件
  • (转)LINQ之路
  • (转)树状数组
  • (转)为C# Windows服务添加安装程序
  • **PyTorch月学习计划 - 第一周;第6-7天: 自动梯度(Autograd)**
  • .[hudsonL@cock.li].mkp勒索加密数据库完美恢复---惜分飞
  • .NET CORE 3.1 集成JWT鉴权和授权2
  • .NET MVC 验证码
  • .net 流——流的类型体系简单介绍
  • .NET6实现破解Modbus poll点表配置文件
  • .NetCore项目nginx发布
  • ;号自动换行