目录
好的总是压箱底,那我猜,幸福也是
—— 24.10.11
一、会话管理_概述
1.为什么需要会话管理
HTTP是无状态协议
无状态就是不保存状态,即无状态协议(stateless),,HTTP协议自身不对请求和响应之间的通信状态进行保存,也就是说,在HTTP协议这个级别,协议对于发送过的请求或者响应都不做持久化处理
简单理解:浏览器发送请求,服务器接收并响应,但是服务器不记录请求是否来自哪个浏览器,服务器没记录浏览器的特征,就是客户端的状态
举例
张三去一家饭馆点了几道菜,觉得味道不错,第二天又去了,对老板说还点上次的那几道菜
无状态: 老板没有记录张三是否来过,更没有记录上次他点了那些菜,张三只能重新再点一遍
有状态: 老板把每次来吃饭的用户都做好记录,查阅一下之前的记录,查到了张三之前的菜单,直接下单
2.会话管理实现的手段
Cookie和Session配合解决
cookie是在客户端保留少量数据的技术,主要通过响应头向客户端响应一些客户端要保留的信息
session是在服务端保留更多数据的技术,主要通过HttpSession对象保存一些和客户端相关的信息
cookie和session配合记录请求状态
举例
张三去银行办业务
张三第一次去某个银行办业务,银行会为张三开户(session),冰箱张三发放一张银行卡(cookie)
张三之后每次去银行,就可以携带之前的银行卡(cookie),银行根据银行卡找到之前张三开的账户(session)
二、会话管理_Cookie
1.cookie概述
cookie是一种客户端会话技术,cookie由服务端产生,它是服务器存放在浏览器的一小份数据,浏览器以后每次访问该服务器的的候都会将这小份数据携带到服务器去。
服务端创建cookie,将cookie放入响应对象中,Tomcat容器将cookie转化为set-cookie响应头,响应给客户端
客户端在收到cookie的响应头时,在下次请求该服务的资源时,会以cookie请求头的形式携带之前收到的Cookie
Cookie具有时效性
cookie是一种键值对格式的数据,从tomcat8.5开始可以保存中文,但是不推荐
由于cookie是存储于客户端的数据,比较容易暴露,一般不存储一些敏感或者影响安全的数据
请求中的多个cookie会进入该数组,请求中如果没有cookie,cookies数组是为null
原理图
2.cookie的时效性
默认情况下Cookie的有效期是一次会话范围内,我们可以通过cookie的setMaxAge()方法让Cookie持久化保存到浏览器上
cookie1.setMaxAge(360); // 单位是秒
会话级Cookie
服务器端并没有明确指定Cookie的存在时间
在浏览器端,Cookie数据存在于内存中
只要浏览器还开着,Cookie数据就一直都在
浏览器关闭,内存中的Cookie数据就会被释放
持久化Cookie
服务器端明确设置了cookie的存在时间(通过Cookie的API设置时间)
cookie1.setMaxAge(360); // 单位是秒
在浏览器端,Cookie数据会被保存到硬盘上
Cookie在硬盘上存在的时间根据服务器端限定的时间来管控,不受浏览器关闭的影响
持久化Cookie到达了预设的时间会被释放
3.Cookie的提交路径
访问互联网资源时不能每次都需要把所有Cookie带上。访问不同的资源时,可以携带不同的Cookie,我们可以通过cokie的setPath(String path)对Cookie的路径进行设置
4.Cookie常用API
// 创建cookie 键值对形式
Cookie cookie1 = new Cookie("keyA", "valueA");
// 设置Cookie的持久化时间
cookie1.setMaxAge(360); // 单位是秒
// 设置Cookie的提交路径
cookie1.setPath("/demo05/ServletB");
三、会话管理_Session
1.HttpSession概述
HttpSession是一种保留更多信息在服务端的一种技术,服务器会为每一个客户端开辟一块内存空间,即session对象,客户端在发送请求时,都可以使用自己的session,这样服务端就可以通过session来记录某个客户端的状态了
原理图
应用场景
1.记录用户的登陆状态,用户登录后,将用户的账号等敏感信息存入session
2.记录用户操作的历史,例如记录用户的访问痕迹,用户的购物车信息等临时性的信息
2.HttpSession的使用
用户提交form表单到SerletA,携带用户名,servletA获取session,将用户名存到session,用户再请求其他任意Servlet,获取之前存储的用户
执行流程图
Boolean判断是否是新创建的cookie对象
3.HttpSession时效性
为什么要设置session的时效
用户量很大之后,Session对象相应的也要创建很多。如果一味创建不释放,那么服务器端的内存迟早要被耗尽。
客户端关闭行为无法被服务端直接侦测,或者客户端较长时间不操作也经常出现,类似这些的情况,就需要对session的时限进行设置了
session的最大闲置时间
默认的session最大闲置时间(两次使用同一个session中的间隔时间)在tomcat/conf/web.xml配置为30分钟
我们可以自己在当前项目的web.xml对最大闲置时间进行重新设定
可以通过HttpSession的API 对最大闲置时间进行设定
// 设置最大闲置时间
session.setMaxInactiveInterval(60);
可以让session失效
// 直接让session失效
session.invalidate();
四、会话管理_三大域对象
1.域对象概述
域对象:
一些用于存储数据和传递数据的对象,传递数据不同的范围,我们称之为不同的域,不同的域对象代表不同的域,共享数据的范围也不同
web项目中,我们一定要熟练使用的域对象分别是:请求域,会话域,应用域
请求域对象是HttpServletRequest,传递数据的范围是一次请求之内及请求转发
会话域对象是HttpSession,传递数据的范围是一次会话之内,可以跨多个请求
应用域对象是ServletContext,传递数据的范围是本应用之内,可以跨多个会话
生活举例:热水器摆放位置不同,使用的范围就不同
1.摆在张三工位下,就只有张三一个人能用
2.摆在办公室的公共区,办公室内的所有人都可以用
3.摆在楼层的走廊区,该楼层的所有人都可以用
三大与对象的数据作用范围图解
请求域
会话域
应用域
所有域放在一起
2.域对象的使用
域对象的API
向域对象中添加/修改数据
void setAttribute(String name,String walue)
从域对象中获取数据
Object getAttribute(String name);
移除域对象中的数据
removeAttribute(String name);
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 {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
// 向请求域存放数据
req.setAttribute("request","requestMessage");
// 向会话域存放数据
HttpSession session = req.getSession();
session.setAttribute("session","sessionMessage");
// 向应用域存放数据
ServletContext application = req.getServletContext();
application.setAttribute("application","applicationMessage");
// 获取请求域数据
String reqMessage = (String) req.getAttribute("request");
System.out.println("请求域:"+reqMessage);
// 请求转发
req.getRequestDispatcher("servletB").forward(req,resp);
}
}
servletB
package Servlet;
import jakarta.servlet.ServletContext;
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 {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException {
// 获取请求域中的数据
String reqMessaage = (String) req.getAttribute("request");
System.out.println("请求域:"+reqMessaage);
// 获取会话域中的数据
HttpSession session = req.getSession();
String sessionMeaage = (String) session.getAttribute("session");
System.out.println("会话域:"+sessionMeaage);
// 获取应用域中的数据
ServletContext application = getServletContext();
String appMessage = (String) application.getAttribute("application");
System.out.println("应用域:"+appMessage);
}
}
应用场景
请求转发时,请求域可以传递数据
请求域内一段放本次请求业务有关的数据,如:查询到的所有部门信息
同一个会话内,不用请求转发,会话域可以传递数据
会话域内一般放本次会话的客户端有关的数据,如:当前客户端登陆的用户
同一个APP内,不同的客户端,应用域可以传递数据
应用域内一般放本程序应用有关的数据,如:Spring框架的IOC容器