Cookie 和 Session
Cookie
什么是Cookie
- Cookie是一个类,只能存储键值对。只有下面一个构造方法
Cookie的创建,负责创建Cookie并发送给客户端并通知浏览器保存
实验的环境
- CookieServlet
package com.atguigu.web;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class CookieServlet extends BaseServlet{
protected void createCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.创建Cookie对象
Cookie cookie = new Cookie("key1","value1");
Cookie cookie1 = new Cookie("key2","value2");
Cookie cookie2 = new Cookie("key3","value3");
//2.通知客户端保存Cookie
resp.addCookie(cookie);
resp.addCookie(cookie1);
resp.addCookie(cookie2);
//3.往客户端打印内容
resp.getWriter().write("cookie创建成功了");
}
}
**由BaseServlet实现对CreateCookie的发射调用
-
cookie的查看:在浏览器中按f12:
需要解决的问题:
-
解决
问题2:我们的cookie对象是怎样就写到了浏览器当中呢?其中的原理是怎样的?
Cookie对象是通过HTTP响应头字段中的Set-Cookie响应头字段发送给浏览器的。当服务器向客户端发送响应时,它会在响应头中添加一个或多个Set-Cookie字段。
当我们的服务器通知客户端进行保存,我们的浏览器将会保存响应头的cookie或者更新他的值 -
cookie创建和保存的原理
-
可以创建多个并保存多个cookie对象
Cookie的获取
- 演示cookie获取
客户端有了cookie后,每次请求都发送给服务器。具体怎样发送的呢?
- cookie获取原理
- 前提是浏览器中已经存在cookie
- 调用CookieServlet中的getCookie方法
//服务器获取客户端的cookie
protected void getCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取服务器发送过来的cookie
final Cookie[] cookies = req.getCookies();
//2.getName获取cookie的key
//3.getValue获取cookie的value
for (Cookie cookie : cookies) {
resp.getWriter().write("Cookie["+cookie.getName()+"="+cookie.getValue()+"]<br>");
}
}
- 我们怎样是获取指定的cookie呢(有时候我们不需要全部是cookie,只需要特定的就可以了)
但是我们发现cookie没有像getparamer()获取参数一样的方法(输出键将回去对应的值)。那我们就只有遍历整个cookie数组然后过滤特定的cookie了
- 在项目中我们查询cookie的这个操作是很常用的,所以我们一般把将这个方法封装在一个工具类中**
- cokieUtils工具类
package com.atguigu.utils;
import javax.servlet.http.Cookie;
//Cookie操作的工具类
public class CookieUtils {
//查找特定名称的cookie对象
public static Cookie findCookie(String name,Cookie[] cookies){
if(name==null||cookies==null||cookies.length==0){
return null;
}
for (Cookie cookie : cookies) {
if(name.equals(cookie.getName())){
return cookie;
}
}
return null;
}
}
cookie值的修改
-
方案一:依据map集合的特性,存储进去一个相同key的map,将会更新集合中相同key的value
-
cookie的值的注意点:
谷歌和火狐浏览器如何查看cookie]
cookie的存活设置
- 默认生命周期
当我们记录下网址,关闭浏览器然后再次打开后查看,刚刚存储的cookie真的消失了
- 值为零,表示马上删除 Cookie
首先需要确保浏览器中已经存在有了cookie - 已经存在的cookie
- 点击删除后服务器发送给浏览器的http协议
此时我们在浏览器中就 可以发现特定的cookie被删除了 - 服务器中立即删除的方法
- 指定cookie存活一段时间
- 我们查看http协议的回复头:
- servlet程序中的存活一段时间的方法
此时当我们关闭浏览器后,重新打开发现我们的cookie值还在
Cookie的path属性
cookie的默认path是/工程名(工程路径)
我们是可以手动设置cookie的path的
- CookieServlet中测试path的函数
//测试cookie的有效path
protected void testPath(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//创建一个cookie
Cookie cookie = new Cookie("key6","Value6");
//设置他的path
//req.getContextPath()获取该请求的工程路径
cookie.setPath(req.getContextPath()+"/abc");//path:/cookie/abc
resp.addCookie(cookie);//将cookie和他的信息发送给客户端
}
- 当我们点击Cookie的路径设置后,会将我们创建号的cookie和path路径发送给浏览器:
但是当我们在浏览器查看发送过来的cookie时。我却发现浏览器中并没有发现刚刚发送过来的cookie - 于是我们查看respose头
原来这是谷歌为了保护隐私的一种做法。只有你的请求地址匹配的上当前cookie的path才能查看该cookie
cookie练习---面输入用户名登录
当我们第一次登录的时候,网站的用户名和密码是空的。当我们输入用户名和密码登录后,退出去再次登录时,我们的用户名已经自动帮我们填写了
- 实现原理图
- 这是登录页面login.jsp
<%--
Created by IntelliJ IDEA.
User: SWT
Date: 2023/10/21
Time: 20:12
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<base href="http://localhost:8080/cookie/">
<title>Title</title>
<form method="get" action="loginServlet">
用户名:<input type="text" name="username" value="${cookie.username.value}" ><br>
密码:<input type="password" name="password" ><br>
登录<input type="submit" >
</form>
</head>
<body>
</body>
</html>
- 处理登录的LoginServlet
package com.atguigu.web;
import com.atguigu.utils.CookieUtils;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class LoginServlet extends BaseServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
login(req,resp);
}
protected void login(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=UTF-8");
//再次访问时将username的值写入到login.jsp中(将会自动将有效的coookie发送给服务器)
final Cookie username1 = CookieUtils.findCookie("username", req.getCookies());
if(username1!=null){
//这里可以不存储到域中,在jsp中直接可以获取到cookie
// final ServletContext servletContext = req.getServletContext();
//servletContext.setAttribute("username",username1.getValue());//将数据存储到域中
}
//获取用户名和密码
final String username = req.getParameter("username");
final String password = req.getParameter("password");
if("swt".equals(username)&&"123456".equals(password)){
resp.getWriter().write("成功登录成功");
//并将username作为cookie对象发送给客户端保存
Cookie cookie = new Cookie("username",username);
cookie.setMaxAge(3600);//设置cookie的有效期
resp.addCookie(cookie);//将cookie和他的信息发送给客户端保存
}else {
resp.getWriter().write("登录失败");
}
}
}
经过实验发现:当我们登录后,然后关闭浏览器打开再次登录,发现我们的用户名已经回显在了登录页面中
注意:我们也可以通过cookie保存到域中,然后在login.jsp中进行回显
- 注意此时需要使用范围比较大的域,因为我们需要关闭浏览器,然后再次打开
Session(会话)
什么是Session会话
如何创建 Session 和获取(id 号,是否为新
注意:如果测试结果一直都是false,大概是浏览器有cookie缓存,打开浏览器设置清理一下就可以了
Session 域数据的存取
- servlet中往session域中存放和取出数据的方法
//往session域中存储数据
protected void setAttribute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.getSession().setAttribute("key","value");
resp.getWriter().write("成功往session域中存储了数据");
}
//往session域中存放数据
protected void getAttribute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
final String value = (String) req.getSession().getAttribute("key");
resp.getWriter().write("key的值为:" + value);
}
对于req.getSession()方法没什么好纠结的。调用这个方法,如果没有session将会创建一个session对象,如果存在就返回这个sessin对象,都是返回session对象,对我们编程没什么影响
Sesssion超时的控制(生命周期的控制)
-
和cookie一样,他的存活时间可以进行控制
-
Session的默认超时及配置
-
默认市场的配置
在 Tomcat 服务器的配置文件 web.xml中默认有以下的配置,它就表示配置了当前 Tomcat 服务器下所有的 Session
超时配置默认时长为:30 分钟
我们也可以在wab.xml中修改我们web工程的session时长(见文档),也可以修改个别session的超时时长 -
修改个别session的超时时长(修改session3秒后超时)
-
servlet中设置超时时长为3秒的方法(值为正数设置超时时长)
此时我们点击按钮将刚刚创建的session设置为3s超时销毁
我们发现一个现象:
1.当我们快速点击Session的创建和获取(id号、是否为新创建查看session是否有再次被创建,返回的一直是false(没有被创建,尽管,此时已经距离点击3秒销毁已经过了2秒)*
2.我们在点击3秒销毁后,等待了3s后,再次点击,查看发现返回了true(sesion被重新创建) -
解释上面(session超时的介绍)
当setMaxInactiveInterval(int time)方法设置为负数为,将超时时长设置为永不超时
浏览器和 Session 之间关联的技术内幕
疑问:以前讲过,session的范围是打开浏览器,然后关闭浏览器,session就没了。但是上面讲的是,session是由超时时长的,默认是30min,那为什么打开浏览器,然后关闭session就没有了呢?
当客户端访问服务器,服务器创建session对象的时候,会创建一个cookie对象。会将session对象的(key=jession value=session的id值)返回给客户端(通过响应头)
cookie的默认生命周期是一次sessin会话,而浏览器关闭则是一次会话结束,此时cookie消失