1.会话
- HTTP是一种无状态协议;
HTTP协议对于发送过请求或者响应都不做持久化处理
- 具体来说就是客户端发送请求,服务器接收请求,但是服务器自身不会记录每一条请求都是由哪一个客户端发出的;
- 会话管理是通过Cookie和Session配合解决
客户端第一次向服务器发请求,服务器会检查客户端是否携带cookie,
如果没有,服务器会为当前客户端创建session对象;
在响应的时候,服务器会向客户端多响应一个信息叫做cookie
接下来的所有请求,只要cookie还在,客户端就能通过cookie找到其session对象
后续一系列的请求响应组成了所谓的会话;
这一系列会话可以分析出用户先前都做了什么事,什么操作
- 学习此章节无非就是学习cookie和session相关的API
1.1 Cookie
-
cookie是服务器产生,存放在浏览器的一小份数据,后续服务器的所有请求都会带着cookie到服务器去;
-
1.创建cookie
-
注意:看上图cookie构造器是键值对进行构造,因此创建需要传入两个参数
-
2.将cookie装入response响应报文
resp.addCookie(cookie1);
- cookie可以创建多个,也可以装入多个
// 1.创建cookieCookie cookie1 = new Cookie("keyA","valueA");Cookie cookie2 = new Cookie("keyB","valueB");Cookie cookie3 = new Cookie("keyC","valueC");// 2.将cookie装入response对象resp.addCookie(cookie1);resp.addCookie(cookie2);resp.addCookie(cookie3);
注意index.jsp存在会干扰cookie session测试,因此创建web工程前先把其删除;
- 测试
创建Servlet类
写入上面代码得到下面所示
从ServletB中获取Cookie
Cookie[] cookies = req.getCookies();
- 如果cookie没有的话,访问时候一定要判断,否则空指针异常,改进如下;
-
如果你没有cookie,那么使用API获取的东西就是null,而不是空数组
-
cookie分类
会话级cookie (默认)
持久级cookie
-
持久化cookie
- 服务器明确设置了cookie时间
- 客户端浏览浏览器的时候cookie数据会被保存在硬盘上
- cookie时间严格受 硬盘管控,不受浏览器关闭的影响
- 如果关闭了,下次加载会继续加载访问时间
-
API设置Cookie时间
cookie.setMaxAge(100);
-
Cookie的提交路径设置
- 这样的好处:Req设置的cookie只会对ServletB进行提交
- 也就是卡号为123的用户去银行,只能去三号柜台使用卡
cookie1.setPath("/ServletB");
1.2 Session
-
Session对象产生之后,服务器会自动的向Response放入cookie,建就是JSESSIONID,值是session的键值对
-
服务器每次对cookie进行读取就能够拿到JSESSIONID,进而获取服务器对应原本的session对象;
- API相关
- 获取Session对象
HttpSession session= req.getSession();
req.getSession();
如果没有Session,那么此APi会创建一个session对象生成一个jsessionid
如果有;会通过jsession找到对应session对象
一次会话之内 | 多个请求使用同一个旧的session |
---|---|
请求不同会话 | 请求与请求之间session不同 |
- 获取session
session.getId()
- 判断是否为新
session.isNew()
- 往session里面放值
session.setAttribute("key","v")
api极为简单,根据英文单词即可知晓作者设计api的思路;见名知意
- session持久化
默认 30min 如果超时,默认会自动清除掉;
30分钟可以自定义
- 定义 cc的session时间直接调用api
ccSession.setMaxInactivaInterval(60); //设置最大激活间隔时间单位s
1.3 三大域对象
1.3.1 域对象概述
域对象: 一些用于存储数据和传递数据的对象,传递数据不同的范围,我们称之为不同的域,不同的域对象代表不同的域,共享数据的范围也不同
- 请求域
- 会话域
- 应用域
整个服务器的应用域有且仅有一个
1.3.2域对象的使用
域对象的API
API | 功能 |
---|---|
void setAttribute(String name,String value) | 向域对象中添加/修改数据 |
Object getAttribute(String name); | 从域对象中获取数据 |
removeAttribute(String name); | 移除域对象中的数据 |
请求域是直接拿着req存放数据
会话域需要拿着req的session去获取数据
应用域直接getServletContext() //ServletContext()就是之前学的全局配置,之前的目的就是获取应用域。
案例需求:
创建工程分别写两个ServletA,ServletB
ServletA分别向请求域,会话域,应用域放入数据;并读取数据
并且将请求转发给ServletB,使B进行数据获取
- ServletA域填写数据获取数据请求转发
@WebServlet("/ServletA")
public class ServletA extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1.向三大域分别存放数据req.setAttribute("K请求域","V请求域");HttpSession session = req.getSession();session.setAttribute("K会话域","V会话域");ServletContext servletContext = getServletContext();servletContext.setAttribute("K应用域","V应用域");// 2.分别获取域 中数据
// req.getAttribute("K请求域");
// Enumeration<String> attributeNames = req.getAttributeNames();
// while (attributeNames.hasMoreElements()){
// System.out.println(attributeNames);
// attributeNames.nextElement();
// }System.out.println(req.getAttribute("K请求域"));System.out.println(session.getAttribute("K会话域"));System.out.println(servletContext.getAttribute("K应用域"));// 3.请求转发req.getRequestDispatcher("/ServletB").forward(req,resp);}
}
- ServletB读取数据
@WebServlet("/ServletB")
public class ServletB extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {HttpSession session = req.getSession();ServletContext servletContext = getServletContext();System.out.println(req.getAttribute("K请求域"));System.out.println(session.getAttribute("K会话域"));System.out.println(servletContext.getAttribute("K应用域"));}
}
- 请求域很小,会话结束,请求内容就丢失
- 会话域,换一个浏览器访问其Session就不同,即便是同一个客户端进行访问,也不行
- 应用域是全局的
1.3.3 小结
- 请求转发时,请求域可以传递数据
请求域内一般放本次请求业务有关的数据,如:查询到的所有的部门信息
- 同一个会话内,不用请求转发,会话域可以传递数据
会话域内一般放本次会话的客户端有关的数据,如:当前客户端登录的用户
- 同一个APP内,不同的客户端,应用域可以传递数据
应用域内一般放本程序应用有关的数据 如:Spring框架的IOC容器