Cookie与Session笔记
1.1 会话管理概述
1.1.1 什么是会话
这里的会话,指的是web开发中的一次通话过程,当打开浏览器,访问网站地址后,会话开始,当关闭浏览器(或者到了过期时间),会话结束。
举个例子:
例如,你在给家人打电话,这时突然有送快递的配送员敲门,你放下电话去开门,收完快递回来后,通话还在保持中,继续说话就行了。
1.1.2 会话管理作用
什么时候会用到会话管理呢?最常见的就是购物车,当我们登录成功后,把商品加入到购物车之中,此时我们无论再浏览什么商品,当点击购物车时,那些加入的商品都仍在购物车中。
在我们的实际开发中,还有很多地方都离不开会话管理技术。比如,我们在论坛发帖,没有登录的游客身份是不允许发帖的。所以当我们登录成功后,无论我们进入哪个版块发帖,只要权限允许的情况下,服务器都会认识我们,从而让我们发帖,因为登录成功的信息一直保留在服务器端的会话中。
通过上面的两个例子,我们可以看出,它是为我们共享数据用的,并且是在不同请求间实现数据共享。也就是说,如果我们需要在多次请求间实现数据共享,就可以考虑使用会话管理技术了。
1.1.3 会话管理分类
在JavaEE的项目中,会话管理分为两类。分别是:客户端会话管理技术和服务端会话管理技术。
客户端会话管理技术
它是把要共享的数据保存到了客户端(也就是浏览器端)。每次请求时,把会话信息带到服务器,从而实现多次请求的数据共享。
服务端会话管理技术
它本质仍是采用客户端会话管理技术,只不过保存到客户端的是一个特殊的标识,并且把要共享的数据保存到了服务端的内存对象中。每次请求时,把这个标识带到服务器端,然后使用这个标识,找到对应的内存空间,从而实现数据共享。
1.2 客户端会话管理技术
1.2.1 Cookie概述
1)什么是Cookie
它是客户端浏览器的缓存文件,里面记录了客户浏览器访问网站的一些内容。同时,也是HTTP协议请求和响应消息头的一部分(在HTTP协议课程中,我们备注了它很重要)。
2)Cookie的API详解
创建Cookie:
方法名 | 作用 |
---|---|
Cookie(String name,String value) | 构造方法创建对象 |
// 演示Cookie的使用
//1.创建cookie,绑定数据key:value
Cookie cookie = new Cookie("msg","你一天挣几爽?");
发送Cookie:
返回值 | 方法名 | 说明 |
---|---|---|
void | addCookie(Cookie cookie) | 向客户端添加Cookie |
//2.通过response发送cookie对象
response.addCookie(cookie);
获取Cookie
返回值 | 方法名 | 说明 |
---|---|---|
Cookie[] | getCookies() | 获取所有的Cookie |
String | getName() | 获取Cookie名字 |
String | getValue() | 获取Cookie的值 |
//1.通过request接受所有cookie
Cookie[] arr = request.getCookies();
//2.遍历数组,拿出每一个cookie
if(arr != null && arr.length != 0){
for (Cookie cookie : arr) {
//2.1获取cookie名字
String name = cookie.getName();
//2.2获取cookie值
String value = cookie.getValue();
System.out.println(name+" : "+value);
}
}
1.2.2 Cookie的细节
-
一次可不可以发送多个cookie?
- 可以创建多个Cookie对象,使用response调用多次addCookie方法发送cookie即可。
// 演示Cookie的使用 //1.创建cookie,绑定数据key:value Cookie cookie1 = new Cookie("msg","你一天挣几爽?"); Cookie cookie2 = new Cookie("anwser","我一年挣0.1爽"); //2.通过response发送cookie对象 response.addCookie(cookie1); response.addCookie(cookie2); System.out.println("cookie发送完成");
-
cookie在浏览器中保存多长时间?
- 默认情况下,当浏览器关闭后,Cookie数据被销毁
- 持久化存储:
- setMaxAge(int seconds)
- 正数:将Cookie数据写到硬盘的文件中。持久化存储。并指定cookie存活时间,时间到后,cookie文件自动失效
- 负数:默认值
- 零:删除cookie信息
- setMaxAge(int seconds)
// 演示Cookie的使用 //1.创建cookie,绑定数据key:value Cookie cookie = new Cookie("msg","你一天挣几爽?"); cookie.setMaxAge(60*60); System.out.println("保存1小时"); //2.通过response发送cookie对象 response.addCookie(cookie);
-
cookie能不能存中文?
-
在tomcat 8 之前 cookie中不能直接存储中文数据。
- 需要将中文数据转码—一般采用URL编码(%E3)
-
在tomcat 8 之后,cookie支持中文数据。特殊字符还是不支持,建议使用URL编码存储,URL解码解析
-
-
cookie共享问题?
假设在一个tomcat服务器中,部署了多个web项目,那么在这些web项目中cookie能不能共享?
- 默认情况下cookie不能共享
- setPath(String path):设置cookie的获取范围。默认情况下,设置当前的虚拟目录
- 如果要共享,则可以将path设置为"/"
// 演示Cookie的使用 //1.创建cookie,绑定数据key:value Cookie cookie = new Cookie("msg","你一天挣几爽?"); //设置cookie范围 cookie.setPath("/"); //2.通过response发送cookie对象 response.addCookie(cookie);
-
Cookie有大小,个数限制。每个网站最多只能存20个cookie,且大小不能超过4kb。同时,所有网站的cookie总数不超过300个。
1.2.3 Cookie案例
记住上一次访问时间
需求:
- 访问一个Servlet,如果是第一次访问,则提示:您好,欢迎您首次访问。
- 如果不是第一次访问,则提示:欢迎回来,您上次访问时间为:显示时间字符串
@WebServlet("/demo7")
public class ServletDemo7 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
//1.判断用户是否第一次访问
//看cookie中有没有lastTime
Cookie lastTime = CookieUtils.getCookie(request, "lastTime");
if(lastTime == null){
//没有,说明第一次访问
//记录这次访问的时间
Date date = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日HH时mm分ss秒");
String format = dateFormat.format(date);
Cookie cookie = new Cookie("lastTime", format);
response.addCookie(cookie);
//返回数据
PrintWriter out = response.getWriter();
out.write("欢迎您,这是您第一次访问!");
}else{
//有,说明之前访问过
//取出上次访问时存入的值
String value = lastTime.getValue();
//记录这次访问的时间
Date date = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日HH时mm分ss秒");
String format = dateFormat.format(date);
Cookie cookie = new Cookie("lastTime", format);
response.addCookie(cookie);
//返回数据
PrintWriter out = response.getWriter();
out.write("欢迎您,您上次访问时间是:"+value);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
CookieUtils:
public class CookieUtils {
public static Cookie getCookie(HttpServletRequest request,String cookieName){
//1.通过请求获取所有Cookie
Cookie[] cookies = request.getCookies();
//2.判断该数组是否有值
if(cookies != null && cookies.length>0){
//3.遍历数组,得到每一个cookie
for (Cookie cookie : cookies) {
//4.判断当前cookie的name,是否是我们要找的, 如果是就将这个cookie返回
String name = cookie.getName();
if(name.equals(cookieName)){
return cookie;
}
}
}
//5.没找到或者数组没值, 就返回null
return null;
}
}
1.3 服务端会话管理概述
1.3.1 HttpSession概述
1)HttpSession对象介绍
它是Servlet规范中提供的一个接口。该接口的实现由Servlet规范的实现提供商提供。我们使用的是Tomcat服务器,它对Servlet规范进行了实现,所以HttpSession接口的实现由Tomcat提供。该对象用于提供一种通过多个页面请求或访问网站来标识用户并存储有关该用户的信息的方法。简单说它就是一个服务端会话对象,用于存储用户的会话数据。
同时,它也是Servlet规范中四大域对象之一的会话域对象。并且它也是用于实现数据共享的。但它与我们之前讲解的应用域和请求域是有区别的。
域对象 | 作用范围 | 使用场景 |
---|---|---|
ServletContext | 整个应用范围 | 当前项目中需要数据共享时,可以使用此域对象。 |
ServletRequest | 当前请求范围 | 在请求或者当前请求转发时需要数据共享可以使用此域对象。 |
HttpSession | 会话返回 | 在当前会话范围中实现数据共享。它可以在多次请求中实现数据共享。 |
2)HttpSession的获取
返回值 | 方法名 | 说明 |
---|---|---|
HttpSession | getSession() | 获取HttpSession对象 |
//获取session
HttpSession session = request.getSession();
3)HttpSession的常用方法
返回值 | 方法名 | 说明 |
---|---|---|
void | setAttribute(String name,Object value) | 设置共享数据 |
Object | getAttribute(String name) | 获取共享数据 |
void | removeAttribute(String name) | 移除共享数据 |
String | getId() | 获取唯一标识名称 |
void | Invalidate() | 让session立即销毁 |
存数据
//获取session
HttpSession session = request.getSession();
//设置值
session.setAttribute("flag","不赢不睡觉");
取数据
//获取值
HttpSession session = request.getSession();
Object flag = session.getAttribute("flag");
System.out.println("flag = " + flag);
删除数据
//获取值
HttpSession session = request.getSession();
session.removeAttribute("flag");
获得session的Id
//获取session的Id
HttpSession session = request.getSession();
String id = session.getId();
System.out.println("id = " + id);
销毁session
HttpSession session1 = request.getSession();
String id1 = session1.getId();
System.out.println("id1 = " + id1);
//销毁session
session1.invalidate();
HttpSession session2 = request.getSession();
String id2 = session2.getId();
System.out.println("id2 = " + id2);
1.3.2 HttpSession的原理
1) Session的原理
HttpSession,它虽然是服务端会话管理技术的对象,但它本质仍是一个Cookie。是一个由服务器自动创建的特殊的Cookie,Cookie的名称就是JSESSIONID,Cookie的值是服务器分配的一个唯一的标识。
当我们使用HttpSession时,浏览器在没有禁用Cookie的情况下,都会把这个Cookie带到服务器端,然后根据唯一标识去查找对应的HttpSession对象,找到了,我们就可以直接使用了。下图就是我们入门案例中,HttpSession分配的唯一标识,同学们可以看到两次请求的JSESSIONID的值是一样的:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JyvBigZK-1649529271888)(C:\Users\Administrator\Desktop\WEB阶段\06_Cookie与Session\讲义\Cookie与Session笔记.assets\image-20210605192500443.png)]
2) Session的细节
-
session什么时候被销毁?
-
服务器关闭
-
session对象调用invalidate() 。
-
session默认失效时间 30分钟
-
-
session用于存储一次会话的多次请求的数据,存在服务器
-
session可以存储任意类型,任意大小的数据
1.3.3 HttpSession的钝化和活化
什么是持久态
把长时间不用,但还不到过期时间的HttpSession进行序列化,写到磁盘上。
我们把HttpSession持久态也叫做钝化。(与钝化相反的,我们叫活化。)
什么时候使用持久化
第一种情况:当访问量很大时,服务器会根据getLastAccessTime来进行排序,对长时间不用,但是还没到过期时间的HttpSession进行持久化。
第二种情况:当服务器进行重启的时候,为了保持客户HttpSession中的数据,也要对HttpSession进行持久化
注意
HttpSession的持久化由服务器来负责管理,我们不用关心。
只有实现了序列化接口的类才能被序列化,否则不行。
1.3.4 Session案例
- 案例需求:
- 访问带有验证码的登录页面
- 用户根据显示的验证码图片输入验证码。
如果验证码输入有误,后台输出: 验证码错误
如果全部输入正确,后台输出: 验证码正确
页面代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>验证码</title>
<script>
window.onload=function () {
//1.获取图片对象
var img = document.getElementById("checkimg");
//2.给图片绑定点击事件
img.onclick=function () {
//为了让浏览器不适用缓存,我们在请求后面加参数
//时间戳
var time = new Date().getTime();
//3.重置src属性
img.src="/day04/checkCode?aa="+time;
}
}
</script>
</head>
<body>
<form action="/day06/demo13" method="post">
<img id="checkimg" src="/day06/checkCode">
<br>
验证码:<input type="text" name="checkCode">
<br>
<button type="submit">提交</button>
</form>
</body>
</html>
修改CheckCodeServlet代码
//生成随机角标
Random ran = new Random();
StringBuilder sb = new StringBuilder();
for (int i = 1; i <= 4; i++) {
int index = ran.nextInt(str.length());
//获取字符
char ch = str.charAt(index);//随机字符
sb.append(ch);
//2.3写验证码
g.drawString(ch+"",width/5*i,height/2);
}
String checkCode_session = sb.toString();
//将验证码存入session
request.getSession().setAttribute("checkCode_session",checkCode_session);
创建后台代码
@WebServlet("/demo13")
public class ServletDemo13 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取传入的验证码
String checkCode = request.getParameter("checkCode");
//获取session中存储的验证码
HttpSession session = request.getSession();
Object checkCode_session = session.getAttribute("checkCode_session");
//验证码一次性的, 所以获取一次之后应该删除
session.removeAttribute("checkCode_session");
//类型转换
String checkCodeSession = String.valueOf(checkCode_session);
//比较判断
if(checkCode.equalsIgnoreCase(checkCodeSession)){
System.out.println("验证码正确");
}else{
System.out.println("验证码错误");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}