会话技术-Cookie
- 基本介绍
- 会话的两种技术
- cookie有什么用?
- cookie介绍
- 二说cookie
- cookie可以用来干啥
- cookie常用方法
- cookie底层实现机制-创建和读取cookie
- 应用实例-读取指定cookie和修改cookie
- cookie生命周期
- 介绍
- 应用实例
- cookie有效路径
- 有效路径规则
- 应用实例
- 作业布置
- cookie注意事项和细节
基本介绍
1.什么是会话?
会话可简单地理解为: 用户开启一个浏览器, 点击多个超链接, 访问服务器多个web资源, 然后关闭浏览器, 整个过程称之为一个会话.
2.会话过程中要解决哪些问题?
1)每个用户在使用浏览器与服务器进行会话的过程中, 不可避免地会产生一些数据, 服务器要想办法帮每个用户保存这些数据.
2)例如: 多个用户点击超链接通过一个servlet各自购买了一个商品, 服务器应该想办法把每一个用户购买的商品保存在各自的地方, 以便于这些用户点结账servlet时, 结账servlet可以得到用户各自购买的商品为用户结账.
会话的两种技术
cookie, Session.
cookie有什么用?
1.大家在访问某个网站的时候, 是否能看到提示你上次登陆网站的时间, 而且要注意的是不同用户上次登陆的时间肯定是不一样的, 这是怎么实现的?
2.大家访问某个购物网站的时候, 是否能看到提示你曾经浏览过的商品, 不同用户浏览的商品肯定不一样, 这是怎么实现的?
3.解决之道-cookie技术
cookie(小甜饼)是客户端技术, 服务器把每个用户的数据以cookie的形式写给用户各自的浏览器. 当用户使用浏览器再去访问服务器中的web资源时, 就会带着各自的数据去. 这样, web资源处理的就是用户各自的数据了.
cookie介绍
二说cookie
1.cookie是服务器在客户端保存的用户信息, 比如登录名, 浏览历史等, 就可以以cookie的方式保存.
2.cookie信息就像是小甜饼(cookie 中文)一样, 数据量并不大, 服务器端在需要的时候可以从客户端/浏览器(通过http协议)读取.
3.这个就是edge浏览器里的cookie信息.
4.再次强调, cookie数据是保存在浏览器的.
cookie可以用来干啥
1.保存上次登陆时间等信息.
2.保存用户名, 密码, 在一定时间内不用重新登陆.
3.网站的个性化, 比如定制网站的服务, 内容.
cookie常用方法
1.cookie有点像一张表(K-V), 分两列, 一个是名字, 一个是值, 数据类型都是String, 都是小量的数据, 如图
2.如果创建一个cookie(在服务端创建的)
cookie cookie = new cookie(String name, String val);
cookie.setMaxAge();//保存时间
3.如何将一个cookie添加到客户端
response.addcookie(cookie);
4.如何读取cookie(在服务端读取cookie信息)
request.getcookies();
cookie底层实现机制-创建和读取cookie
需求: 演示Cookie底层实现机制, 创建和读取Cookie.
代码实现
1.新建java项目 cookie-session
2.引入servlet-api.jar
3.参考 IDEA 2022.3开发JavaWeb工程
4.创建src/com/zzw/cookie/CreateCookie.java
/**
* 演示如何创建cookie,并保存到浏览器
*/
public class CreateCookie extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("CreateCookie doPost 被调用...");
//1.创建一个Cookie对象
// username是该cookie的名字,是唯一的,可以理解为key; zzw 是该cookie的值
// 可以创建多个Cookie对象,这里只创建了一个. 这时cookie在服务器端, 还没有在浏览器端
Cookie username = new Cookie("username", "zzw");
Cookie email = new Cookie("email", "978964140@qq.com");
//2.将cookie发送给浏览器, 让浏览器将该cookie保存
response.setContentType("text/html;charset=utf-8");
response.addCookie(username);
response.addCookie(email);
PrintWriter writer = response.getWriter();
writer.print("<h1>创建cookie成功!</h1>");
writer.flush();
writer.close();
}
}
配置web.xml
<servlet>
<servlet-name>CreateCookie</servlet-name>
<servlet-class>com.zzw.cookie.CreateCookie</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CreateCookie</servlet-name>
<url-pattern>/createCookie</url-pattern>
</servlet-mapping>
5.浏览器访问 https://localhost:8080/cookie_session/createCookie, 使用浏览器抓包分析 创建 Cookie 的底层机制
6.创建src/com/zzw/cookie/ReadCookie.java
public class ReadCookies extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
/*读取浏览器/客户端发送来的cookie信息*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("ReadCookies 被调用...");
//1.通过request对象获取cookie信息
Cookie[] cookies = request.getCookies();
//2.遍历cookies信息,先判断一下
if (cookies != null && cookies.length != 0) {
for (Cookie cookie : cookies) {
System.out.println("cookie: 名字=" + cookie.getName() + ", 值=" + cookie.getValue());
}
}
//3.给浏览器返回信息
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.print("<h1>读取cookies信息成功</h1>");
writer.flush();
writer.close();
}
}
配置web.xml
<servlet>
<servlet-name>ReadCookie</servlet-name>
<servlet-class>com.zzw.cookie.ReadCookie</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ReadCookie</servlet-name>
<url-pattern>/readCookie</url-pattern>
</servlet-mapping>
7.浏览器访问 https://localhost:8080/cookie_session/readCookie, 使用浏览器抓包分析 创建 Cookie 的底层机制
8.不同会话, jsessionid不同.
1.提示: 访问Servlet(比如 http://localhost:8080/cs/updatecookie)不会生成JSESSIONID, 访问http://localhost:8080/cs/才会生成
2.要关闭浏览器再开一个新的, 才能产生一个新的session会话
应用实例-读取指定cookie和修改cookie
1.创建src/com/zzw/cookie/utils/CookieUtils.java
public class CookieUtils {
//编写一个方法, 返回指定名字的cookie
public static Cookie readCookieByName(String name, Cookie[] cookies) {
//判断输入的参数格式是否正确
if (name == null || "".equals(name) || cookies == null || cookies.length == 0) {
return null;
}
//遍历cookie数组
for (Cookie cookie : cookies) {
if (name.equals(cookie.getName())) {
return cookie;
}
}
return null;
}
}
2.创建src/com/zzw/cookie/ReadCookieByName.java
public class ReadCookieByName extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("ReadCookieByName doPost() 被调用...");
//1.读取到中文cookie
Cookie[] cookies = request.getCookies();
Cookie cookie = CookieUtils.readCookieByName("username", cookies);
String value = cookie.getValue();
System.out.println("读取到cookie值: " + value);//URL
//2.解码
value = URLDecoder.decode(value, "UTF-8");
System.out.println("解码后 中文cookie值: " + value);
//3.返回给浏览器信息
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.print("<h1>读取到中文cookie并解码成功</h1>");
writer.flush();
writer.close();
}
}
配置web.xml
<servlet>
<servlet-name>ReadCookieByName</servlet-name>
<servlet-class>com.zzw.cookie.ReadCookieByName</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ReadCookieByName</servlet-name>
<url-pattern>/readCookieByName</url-pattern>
</servlet-mapping>
3.浏览器访问 https://localhost:8080/cookie_session/readCookieByName
4.创建src/com/zzw/cookie/UpdateCookie.java
public class UpdateCookie extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("UpdateCookie doPost() 被调用...");
//1.根据name去查找指定cookie
String cookieName = "username";
Cookie[] cookies = request.getCookies();
Cookie cookie = CookieUtils.readCookieByName(cookieName, cookies);
if (cookie == null) {//在该浏览器中没有该cookie
System.out.println("当前访问服务端的浏览器没有该cookie");
return;
}
//2.修改cookie
cookie.setValue("~~赵志伟~~");
System.out.println("=================修改后的cookie信息=================");
for (Cookie cookie2 : cookies) {
System.out.println("cookie: 名字=" + cookie2.getName() + ", 值=" + cookie2.getValue());
}
//2.将cookie发送给浏览器, 让浏览器将该cookie保存
response.setContentType("text/html;charset=utf-8");
response.addCookie(cookie);
PrintWriter writer = response.getWriter();
writer.print("<h1>完成修改cookie</h1>");
writer.flush();
writer.close();
}
}
配置web.xml
<servlet>
<servlet-name>UpdateCookie</servlet-name>
<servlet-class>com.zzw.cookie.UpdateCookie</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UpdateCookie</servlet-name>
<url-pattern>/updateCookie</url-pattern>
</servlet-mapping>
5.浏览器访问 localhost:8080/cookie_session2/updateCookie, 完成测试
cookie生命周期
介绍
1.cookie的生命周期是指如何管理cookie, 什么时候被销毁(删除).
2.setMaxAge()
1)正数: 表示在指定的秒数后过期, 但过期后仍存在于浏览器中.
2)0: 表示马上在浏览器端删除cookie.
3)负数: 表示浏览器关闭, cookie就会被删除(默认值是-1).
应用实例
需求: 演示Cookie的生命周期
代码实现
1.创建src/com/zzw/cookie/CookieLive.java
, 测试 正数 指定的秒数后过期
public class CookieLive extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("CookieLive doPost() 被调用...");
//演示创建一个cookie, 生命周期为30s
Cookie cookie = new Cookie("address", "山东省");
//解读
//1.从创建该cookie开始计时, 30秒后无效
//2.浏览器根据创建的时间开始计时, 到30秒后, 就认为该cookie无效
//3.如果该cookie无效, 那么浏览器会在发出http协议时, 就不再携带该cookie
cookie.setMaxAge(30);
//4.将这个cookie写回到浏览器
response.setContentType("text/html;charset=utf-8");
response.addCookie(cookie);
PrintWriter writer = response.getWriter();
writer.write("<h1>设置声明周期成功</h1>");
writer.flush();
writer.close();
}
}
配置web.xml
<servlet>
<servlet-name>CookieLive</servlet-name>
<servlet-class>com.zzw.cookie.CookieLive</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CookieLive</servlet-name>
<url-pattern>/cookieLive</url-pattern>
</servlet-mapping>
2.浏览器访问 http://localhost:8080/cookie_session2/cookieLive, 注意抓包看数据
3.修改src/com/zzw/cookie/CookieLive.java
, 测试0 马上在浏览器端删除
public class CookieLive extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("CookieLive doPost() 被调用...");
//演示如何删除一个cookie, 比如username
//1.先得到username cookie
Cookie[] cookies = request.getCookies();
Cookie cookie = CookieUtils.readCookieByName("username", cookies);
if (cookie == null) {
System.out.println("没有找到cookie, 无法将其删除");
return;
}
//2.将其生命周期设置为0, 等价于让浏览器直接删除该cookie
//说明: 该cookie会被浏览器直接在存储中删除
cookie.setMaxAge(0);
response.addCookie(cookie);
//4.将这个cookie写回到浏览器
response.setContentType("text/html;charset=utf-8");
response.addCookie(cookie);
PrintWriter writer = response.getWriter();
writer.write("<h1>删除cookie成功</h1>");
writer.flush();
writer.close();
}
}
4.浏览器访问 http://localhost:8080/cookie_session2/cookieLive, 注意抓包看数据
访问之后~
这里为何会有两个Set-cookie?
在这个示例中,setCookie 方法展示了如何在Java Servlet中同时设置和删除cookie。
public class CookieExample {
public void setCookie(HttpServletResponse response) {
// 设置新的cookie
Cookie cookie = new Cookie("username", "zzw");
cookie.setMaxAge(60); // 60秒后过期
response.addCookie(cookie);
// 删除已有的cookie
Cookie deleteCookie = new Cookie("username", "zzw");
deleteCookie.setMaxAge(0); // 立即过期
response.addCookie(deleteCookie);
}
}
5.修改src/com/zzw/cookie/CookieLive.java
, 测试复数(默认) 浏览器关闭, cookie就会被删除
public class CookieLive extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/************************************
*默认的会话级别的Cookie[即浏览器关闭就销毁了]
************************************/
Cookie cookie = new Cookie("email", "978964140@qq.com");
cookie.setMaxAge(-1);
//4.将这个cookie写回到浏览器
response.setContentType("text/html;charset=utf-8");
response.addCookie(cookie);
PrintWriter writer = response.getWriter();
writer.write("<h1>设置声明周期成功</h1>");
writer.flush();
writer.close();
}
}
6.浏览器访问 http://localhost:8080/cookie_session2/cookieLive, 注意抓包看数据
cookie有效路径
有效路径规则
1.Cookie有效路径Path的设置
2.Cookie的Path属性可以有效地过滤哪些Cookie可以发送给服务器, 哪些不发. Path属性是通过请求的地址来进行有效的过滤.
3.规则如下:
cookie1.setPath = /工程路径
cookie2.setPath = /工程路径/aaa
请求地址: http:// ip:端口/工程路径/资源
cookie1 会发送给浏览器
cookie2 不会发送给浏览器
请求地址: http:// ip:端口/工程路径/aaa/资源
cookie1 会发送给服务器
cookie2 会发送给服务器
应用实例
1.创建src/com/zzw/cookie/CookiePath.java
public class CookiePath extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("CookiePath doPost() 被调用...");
//1.创建两个cookie对象
Cookie usernameCookie = new Cookie("username", "张三");
Cookie addressCookie = new Cookie("address", "济宁");
//2.设置不同的有效路径
// usernameCookie的有效路径是 /cookie_session
usernameCookie.setPath(request.getContextPath());//设置到工程路径下
// addressCookie的有效路径是 /cookie_session/zhao
addressCookie.setPath(request.getContextPath() + "/zhao");
//说明: 如果我们没有设置cookie的有效路径, 默认就是 /工程路径
//3.保存到浏览器
response.setContentType("text/html;charset=utf-8");
response.addCookie(usernameCookie);
response.addCookie(addressCookie);
PrintWriter writer = response.getWriter();
writer.print("<h1>设置cookie有效路径成功<h1>");
writer.flush();
writer.close();
}
}
配置web.xml
<servlet>
<servlet-name>CookiePath</servlet-name>
<servlet-class>com.zzw.cookie.CookiePath</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CookiePath</servlet-name>
<url-pattern>/cookiePath</url-pattern>
</servlet-mapping>
3.浏览器访问 http://localhost:8080/cookie_session2/cookiePath, 注意抓包看数据
读取一下cookie
切换路径 /cookie_session/zhao/readCookie
作业布置
需求: 完成自动填写登录账户应用案例, 如果用户登录成功, 则下次登录自动填写登录账户.
1)如果用户名是zhaozhiwei
, 密码是123456
, 则认为该用户合法, 登录成功, 否则登陆失败
2)要求实现如果登录成功, 则该用户, 在3天内登录, 可以自动填写其登录名.
3)提示: 登陆页面需要使用servlet
返回, 而不能使用html
.
代码实现
1.创建src/com/zzw/cookie/LoginHtmlServlet.java
粘贴前端代码时, 把\" 换成 ’ 即可.
public class LoginHtmlServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("LoginHtmlServlet doPost() 被调用...");
Cookie[] cookies = request.getCookies();
Cookie usernameCookie = CookieUtils.readCookieByName("username", cookies);
String username = "";
if (usernameCookie != null) {
username = usernameCookie.getValue();
}
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.print("<!DOCTYPE html>\n" +
"<html lang='en'>\n" +
"<head>\n" +
" <meta charset='UTF-8'>\n" +
" <title>用户登录</title>\n" +
"</head>\n" +
"<body>\n" +
"<h1>用户登陆页面</h1>\n" +
"<form action='/cookie_session/login' method='post'>\n" +
" 用户名:<input type='text' name='username' value='" + username + "'/><br/><br/>\n" +
" 密 码:<input type='password' name='pwd'/></br><br/>\n" +
" <input type='submit' value='登陆'/>\n" +
"</form>\n" +
"</body>\n" +
"</html>");
}
}
配置web.xml
<servlet>
<servlet-name>LoginHtmlServlet</servlet-name>
<servlet-class>com.zzw.cookie.homework.LoginHtmlServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginHtmlServlet</servlet-name>
<url-pattern>/loginHtml</url-pattern>
</servlet-mapping>
2.浏览器请求 http://localhost:8080/cookie_session/loginHtml, 准备登录
3.创建src/com/zzw/cookie/homework/LoginServlet.java
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
String username = request.getParameter("username");
String pwd = request.getParameter("pwd");
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
if ("赵志伟".equals(username) && "123456".equals(pwd)) {
writer.print("<h1>该用户合法, 登陆成功</h1>");
//将登陆成功的用户名, 以cookie的形式, 保存到浏览器
Cookie cookie = new Cookie("username", username);
//在cookie中数据保存3天
cookie.setMaxAge(60 * 60 * 24 * 3);
response.addCookie(cookie);
} else {
writer.print("<h1>登陆失败</h1>");
}
writer.flush();
writer.close();
}
}
配置web.xml
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.zzw.cookie.homework.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
4.点击登录
根据usernameCookie的有效路径, 在下次启动浏览器后, 访问http://localhost:8080/cookie_session/ 才会看到这个cookie
cookie注意事项和细节
1.一个cookie只能标识一种信息, 它至少含有一个标识该信息的名称(Name)和设置值(Value).
2.一个Web站点可以给一个浏览器发送多个cookie, 一个浏览器也可以存储多个Web站点提供的cookie.
.
3.cookie的总数量没有限制, 但是每个域名的cookie数量和每个cookie的大小是有限制的(不同的浏览器限制不同), cookie不适合存放数据量大的信息.
4.注意, 删除cookie时, Path必须一致, 否则不会删除.
5.如果存放中文的cookie, 会报错, 可以通过url编码和解码解决
1)创建src/com/zzw/cookie/EncoderCookie.java
public class EncoderCookie extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("EncoderCookie doPost() 被调用...");
//1.创建中文cookie
//(1)如果直接存放中文的cookie, 报错
//(2)解决方案: 将中文编码成 URL编码
//(3)编码后, 再保存cookie即可
String name = URLEncoder.encode("赵志伟", "utf-8");
Cookie cookie = new Cookie("username", name);
//2.保存到浏览器
response.addCookie(cookie);
//3.给浏览器返回信息
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.print("<h1>设置cookie成功</h1>");
writer.flush();
writer.close();
}
}
配置web.xml
<servlet>
<servlet-name>EncoderCookie</servlet-name>
<servlet-class>com.zzw.cookie.EncoderCookie</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>EncoderCookie</servlet-name>
<url-pattern>/encoderCookie</url-pattern>
</servlet-mapping>
2.创建src/com/zzw/cookie/ReadCookie2.java
public class ReadCookie2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("ReadCookie2 doPost() 被调用...");
//1.读取到中文cookie
Cookie[] cookies = request.getCookies();
Cookie cookie = CookieUtils.readCookieByName("username", cookies);
String value = cookie.getValue();
System.out.println("读取到cookie值: " + value);//URL
//2.解码
value = URLDecoder.decode(value, "UTF-8");
System.out.println("解码后 中文cookie值: " + value);
//3.返回给浏览器信息
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.print("<h1>读取到中文cookie并解码成功</h1>");
writer.flush();
writer.close();
}
}
配置web.xml
<servlet>
<servlet-name>ReadCookie2</servlet-name>
<servlet-class>com.zzw.cookie.ReadCookie2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ReadCookie2</servlet-name>
<url-pattern>/readCookie2</url-pattern>
</servlet-mapping>
3.测试