会话技术 Cookie&Session
1 会话技术简介
1.1 存储客户端的状态
由⼀个问题引出今天的内容,例如⽹站的购物系统,⽤户将购买的商品信息存储到哪⾥?因为 Http协议是⽆状态的,也就是说每个客户访问服务器端资源时,服务器并不知道该客户端是谁, 所以需要会话技术识别客户端的状态。会话技术是帮助服务器记住客户端状态(区分客户端)。
1.2 会话技术
浏览器第⼀次给服务器资源发送请求,会话建⽴,直到有⼀⽅断开为⽌的过程,称为⼀次会话。 会话技术就是记录这次会话中客户端的状态与数据的。⼀次会话中包含多次请求和响应。
- 功能:在⼀次会话的范围内的多次请求间,共享数据
- ⽅式:
- 客户端会话技术:Cookie
数据存储在客户端本地,减少服务器端的存储的压⼒,安全性不好,客户端可以清除 cookie
- 客户端会话技术:Cookie
- 服务器端会话技术:Session
将数据存储到服务器端,安全性相对好,增加服务器的压⼒。
2. Cookie技术
- Cookie技术是将⽤户的数据存储到客户端的技术
- cookie的本质: 本质就是添加一个响应头 set-cookie ,将cookie存到客户端
- 请求头信息 cookie 将cookie携带到服务器端
本质就是:将客户端的信息存储在cooKie里面,通过请求主动携带cookie,通过响应添加cookie ,cookie默认的携带路径是当前目录,默认生命周期为添加cookie到关闭客户端,可以通过改变生命周期来长时间保存cookie
实现流程:
- 创建Cookie对象,绑定数据:new Cookie(String name, String value)
- . 发送/添加 Cookie对象 :response.addCookie(Cookie cookie);
- 获取Cookie,拿到数据 :Cookie[] request.getCookies() ,然后数组的遍历
- 中文支持:
编码: URLEncoder.encode("张三", "utf-8");
解码: URLDecoder.decode(value, "utf-8");
@WebServlet("/Demo03Servlet")
public class Demo03Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 向客户端传输cookie对象
// 1.创建cookie对象
Cookie cookie1 = new Cookie("username","zhangsan");
Cookie cookie2 = new Cookie("password","123456");
// 2.发送cookie给客户端
resp.addCookie(cookie1);
resp.addCookie(cookie2);
//新的Servlet类中
// 从客户端获得cookie对象
// 1.获得所有的cookie
Cookie[] cookies = req.getCookies();
if (cookies != null) {
// 2.遍历cookie对象, 找到想要的那个cookie
for (Cookie cookie : cookies) {
if (cookie.getName().equals("password")) {
resp.getWriter().write(cookie.getValue());
}
}
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
实现原理:
基于响应头set-cookie和请求头cookie实现
2.1 cookie的生命周期和携带路径
- 默认的生命周期: 会话结束就删除了(销毁)
- 设置生命周期: setMaxAge(int秒)
- 携带路径:客户端携带cookie是有条件的, 不是访问所有的网页, 都会将cookie携带过来
在访问某一些特定网页, 客户端才会主动将cookie携带到服务器, 这些特定网页称之为cookie的携带路径 - 默认的携带路径: 当前目录
- 携带路径的设置:
/day05/cookie/Demo1Servlet - set-cookie
/day05/cookie/Demo2Servlet - 可以携带
/day05/Demo3Servlet - 和Demo1是同一个应用 "/day05"
/day05/index.jsp
/day04/Demo1Servlet - 和Demo1是同一个服务器 "/"
设置路径:最大携带路径是当前服务器--"/" ,当前应用 -- request.getContextPath();
@WebServlet("/cookie/Demo1Servlet")
public class Demo1Servlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie cookie1 = new Cookie("username", "zhangsan");
Cookie cookie4 = new Cookie("username", "lisi");
Cookie cookie2 = new Cookie("password", "123456");
// 将中文进行编码 ,下面的方法会编译成16进制 这样才可以保存在请求头里面
String name = URLEncoder.encode("张三", "utf-8");
Cookie cookie3 = new Cookie("name", name);
// cookie1是默认生命周期, 默认的携带路径
// cookie2修改生命周期
// 想要删除cookie, 就设置setMaxAge(0)
cookie2.setMaxAge(60 * 5);
// cookie2设置携带路径为当前应用 [当前服务器 / ]
cookie2.setPath(request.getContextPath());
cookie1.setPath("/");
//添加cookie
response.addCookie(cookie1);
response.addCookie(cookie2);
response.addCookie(cookie3);
response.addCookie(cookie4);
//新的servlet
Cookie[] cookies = request.getCookies();
for (Cookie cookie : cookies) {
if (cookie.getName().equals("name")) {
String value = cookie.getValue();
System.out.println(value);
// 将字符串进行解码
value = URLDecoder.decode(value, "utf-8");
System.out.println(value);
}
}
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
2.2 cookie的细节
- 什么是相同的cookie?
- cookie的name要一致
- cookie的携带路径要一致
- 一次可以发送/添加 多个cookie
- 在默认情况下关闭浏览器/服务器 就会销毁所有的cookie ,持久化cookie就可以长时间在服务器保存cookie ,持久化后关闭服务器 持久化的cookie不会被销毁 ,除非到期或者手动销毁
- 持久化cookie:使得生命周期最大化 setMaxAge(int seconds)
- 正数:将Cookie数据写到硬盘的⽂件中。持久化存储。并指定cookie存活时间, 时间到后,cookie⽂件⾃动失效 ,负数:默认值 ,零:删除cookie信息
4. cookie共享问题?
- 假设在⼀个tomcat服务器中,部署了多个web项⽬,那么在这些web项⽬中cookie能 不能共享?
- 默认情况下cookie不能共享 setPath(String path):设置cookie的获取范围。
- 默认情况下,设置当前的虚拟⽬ 录 如果要共享,则可以将path设置为"/"
- 不同的tomcat服务器间cookie共享问题?
- setDomain(String path):如果设置⼀级域名相同,那么多个服务器之间cookie可 以共享
- setDomain(".baidu.com"),那么tieba.baidu.com和news.baidu.com中cookie可 以共享
2.3 Cookie的特点和作⽤
特点:
- 1. cookie存储数据在客户端浏览器
- 2. 浏览器对于单个cookie 的⼤⼩有限制(4kb),以及对同⼀个域名下的总cookie数量也有限制 (20个)
作⽤:
- 1. cookie⼀般⽤于存出少量的不太敏感的数据
- 2. 在不登录的情况下,完成服务器对客户端的身份识别
3.Session技术
Session技术是将数据存储在服务器端的技术,会为每个客户端都创建⼀块内存空间存储客户的 数据,但客户端需要每次都携带⼀个标识ID去服务器中寻找属于⾃⼰的内存空间。所以说 Session的实现是基于Cookie,Session需要借助于Cookie存储客户的唯⼀性标识JSESSIONID。
注:如果服务器监测到客户端已有对应session, 就将这个session返回
如果服务器没有监测到对应session, 就创建新的session对象
服务器通过存客户端的请求携带过来的存储在cookie的JSESSIONID的来识别对应sestion;
实现步骤:
- . 获取HttpSession对象:
HttpSession session = request.getSession();
此⽅法会获得专属于当前会话的Session对象,如果服务器端没有该会话的Session对象会创 建⼀个新的Session返回,如果已经有了属于该会话的Session直接将已有的Session返回 (实质就是根据JSESSIONID判断该客户端是否在服务器上已经存在session了),创建session的同时会自动生成JSESSIONID;
3.1 原理
Session的实现是依赖于Cookie的。创建session的同时会自动生成JSESSIONID,
JSESSIONID保存在客户端的cookie里面 ,一个客户端对一个服务器只有一个JSESSIONID;
每次创建新的Session会改变JSESSIONID的值 ,相当于JSESSIONID 指向了新的Session对象,
session对象不会跟着关闭服务器而销毁 ,关闭服务器后会保存在硬盘里面
3.2 细节
- 1. 当客户端关闭后,服务器不关闭,两次获取session是否为同⼀个?
- 默认情况下。不是。
- 如果需要相同,则可以创建Cookie,键为JSESSIONID,设置最⼤存活时间,让cookie 持久化保存。原理是创建相同的cookie 把原理的给覆盖掉
// 设置持久化时间 Cookie cookie = new Cookie("JSESSIONID", id); cookie.setPath(request.getContextPath()); //设置携带到当前应用 cookie.setMaxAge(Integer.MAX_VALUE); response.addCookie(cookie);
-
2. 客户端不关闭,服务器关闭后,两次获取的session是同⼀个吗?
-
不是同⼀个,但是要确保数据不丢失。tomcat⾃动完成以下⼯作:
-
session的钝化
在服务器正常关闭之前,将session对象序列化到硬盘上 -
session的活化
在服务器启动后,将session⽂件转化为内存中的session对象即可
-
-
3. session什么时候被销毁?
1.服务器非正常关闭
2. session对象调⽤invalidate()
3.session超时 , session默认失效时间 30分钟(从跟服务器没有任何交流开始计算) -
选择性配置修改
<session-config> <session-timeout>30</session-timeout> </session-config>
@WebServlet("/Demo3Servlet")
public class Demo3Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
//Session -- 在服务器存储数据 -- 域对象 -- 依赖于Cookie技术
//如果服务器检测到客户端有Session(用cookie对象的 JSESSIONID来检测) 那么就会用这个Session
//1.session的创建 ,创建的同时会自动创建一个cookie对象来给这个session编号 -- session 的 ID -- 每一个客户端只有一个
HttpSession session = req.getSession();
session.setAttribute("name","张三");
//2. session的销毁 ,可以设置超时销毁时间 ,也可以手动销毁 ,数据都保存在硬盘里面 worck文件
//获得session的ID 叫 -- JSESSIONID
String id = session.getId();
resp.getWriter().write(id);
//3.session的持久化 ,因为seesion的ID是cookie对象 ,默认一次会话结束就ID会消失 ,所以就让ID的生命周期最大化就可以
// 创建相同ID 然后修改生命周就会原来的被覆盖
Cookie cookie = new Cookie("JSESSIONID",id);
cookie.setMaxAge(Integer.MAX_VALUE);
resp.addCookie(cookie);
//输出数据session中保存的数据
String str = req.getSession().getAttribute("name").toString();
resp.getWriter().write("你好bro"+str);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
3.4 session的特点
- 1. session⽤于存储⼀次会话的多次请求的数据,存在服务器端
- 2. session可以存储任意类型,任意⼤⼩的数据
4 . session与Cookie的区别
1. session存储数据在服务器端,Cookie在客户端
2. session没有数据⼤⼩限制,Cookie有
3. session数据安全,Cookie相对于不安全
4. session可以存储任意类型数据,Cookie只能存储字符串类型
用处:
- cookie: 自动登录使用的账号,密码[Filter]; 未登录状态下的购物车信息等
- session: 登录后的用户信息(登录状态); 验证码验证[ajax]
5.四大域对象
域对象:
- ServletContext域的范围: 一次应用 , 每个web应有只有一个
- 创建:属于应用的域对象,当web被加载或者部署时创建,
- 销毁:当关闭服务器,或者卸载部署时销毁
- session域的范围: 一次会话 -- 持久化可以增大范围
- 创建:第一次调用 request.getSession()方法时,也就是开启会话
- 销毁:服务器非正常关闭,session超时 ,手动销毁invalidate()
- Request域的范围: 一次请求 -- 持久化可以增大范围
- 创建:发送一次请求时创建
- 销毁:结束一次请求
- pageContext域的范围: 当前页面
- 创建:是jsp页面的域对象 ,打开当前页面就创建
- 销毁:关闭当前页面 ,只在当前页面内使用