目录
Web 开发会话技术之 -Cookie
会话
基本介绍
1. 什么是会话?
2. 会话过程中要解决的一些问题?
CreateCookie
访问 CreateCookie.java, 使用浏览器抓包分析 , 创建 Cookie 的底层机制
ReadCookie.java
访问 ReadCookie.java, 使用浏览器抓包分析 读取 Cookie 的底层机制.
不同会话,jsessionid 不同
代码
读取指定 Cookie
工具类
-修改 Cookie
介绍
代码示例
3. 完成测试 , 注意抓包看数据
有效路径规则
3. 规则如下:
代码示例
3. 完成测试 , 注意抓包看创建 Cookie 时,返回的数据
4. 完成测试 , 注意抓包看读取 Cookie 时,返回的数据
代码示例
html页面
java
Cookie 注意事项和细节
代码解决
设置
解码
Web 开发会话技术之 -Cookie
会话
基本介绍
1. 什么是会话?
会话可简单理解为:用户开一个浏览器,点击多个超链接,访问服务器多个 web 资源,然
后关闭浏览器,整个过程称之为一个会话。
2. 会话过程中要解决的一些问题?
1) 每个用户在使用浏览器与服务器进行会话的过程中,不可避免各自会产生一些数据,服
务器要想办法为每个用户保存这些数据
2) 例如:多个用户点击超链接通过一个 servlet 各自购买了一个商品,服务器应该想办法
把每一个用户购买的商品保存在各自的地方,以便于这些用户点结帐 servlet 时,结帐
servlet 可以得到用户各自购买的商品为用户结帐。
cookie 技术
Cookie是客户端技术,服务器把每个用户的数据以 cookie 的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的 web 资源时,就会带着各自的数据去。这样,web 资源处理的就是用户各自的数据了。【简单示意图】
cookie 介绍
二说 cookie
1. Cookie 是服务器在客户端保存用户的信息,比如登录名,浏览历史等, 就可以以 cookie方式保存.
2. Cookie 信息就像是小甜饼(cookie 中文)一样,数据量并不大,服务器端在需要的时候可以从客户端/浏览器读取(http 协议),可以通过图来理解
再次说明: cookie 数据是保存在浏览器的.
cookie 可以用来做啥
1. 保存上次登录时间等信息
2. 保存用户名,密码, 在一定时间不用重新登录
3. 网站的个性化,比如定制网站的服务,内容
cookie 基本使用
cookie 常用方法
1. Cookie 有点象一张表(K-V),分两列,一个是名字,一个是值,数据类型都是 String , 如图
2. 如何创建一个 Cookie(在服务端创建的)
Cookie c=new Cookie(String name,String val);
c.setMaxAge();//保存时间
3. 如何将一个 Cookie 添加到客户端
response.addCookie(c);
4. 如何读取 cookie(在服务器端读取到 cookie 信息)
request.getCookies();
cookie 底层实现机制-创建和读取 Cookie
1. 需求: 演示 Cookie 底层实现机制, 创建和读取Cookie
CreateCookie
/*** 演示如何创建cookie,并保存到浏览器*/
public class CreateCookie extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("CreateCookie 被调用...");//1. 创建一个Cookie对象//1) username 该cookie的名字 是唯一, 可以理解成是key//2) xxx : 该cookie的值//3) 可以创建多个cookie,老师就创建了一个//4) 这是cookie在服务器端, 还没有到浏览器Cookie cookie = new Cookie("username", "tom");Cookie cookie2 = new Cookie("email", "tom@qq.com");response.setContentType("text/html;charset=utf-8");//2. 将cookie发送给浏览器, 让浏览器将该cookie保存response.addCookie(cookie);response.addCookie(cookie2);PrintWriter writer = response.getWriter();writer.println("<h1>创建cookie成功~</h1>");writer.flush();writer.close();}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}
}
访问 CreateCookie.java, 使用浏览器抓包分析 , 创建 Cookie 的底层机制
ReadCookie.java
/*** 读取从浏览器发送来的cookie信息[底层仍然是http协议]*/
public class ReadCookies extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("ReadCookies 被调用..");//1. 通过request对象读取cookie信息Cookie[] cookies = request.getCookies();//2. 遍历cookieif (cookies != null && cookies.length != 0) {for (Cookie cookie : cookies) {System.out.println("cookie name= " + cookie.getName()+ " value= " + cookie.getValue());}}//3. 给浏览器返回信息response.setContentType("text/html;charset=utf-8");PrintWriter writer = response.getWriter();writer.println("<h1>读取cookie信息成功~</h1>");writer.flush();writer.close();}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}
}
访问 ReadCookie.java, 使用浏览器抓包分析 读取 Cookie 的底层机制.
不同会话,jsessionid 不同
代码
读取指定 Cookie
public class ReadCookieByNameServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//System.out.println("ReadCookieByNameServlet 被调用..");//得到指定的cookie的value//1. 先得到浏览器携带的所有cookieCookie[] cookies = request.getCookies();//2. 使用工具类来获取指定的cookieCookie emailCookie = CookieUtils.readCookieByName("username", cookies);if(null != emailCookie) {System.out.println("得到cookie name=" + emailCookie.getName()+ " value= " + emailCookie.getValue());} else {System.out.println("sorry, 没有这个cookie");}//3. 给浏览器返回信息response.setContentType("text/html;charset=utf-8");PrintWriter writer = response.getWriter();writer.println("<h1>完成读取cookie的任务..</h1>");writer.flush();writer.close();}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}
}
工具类
public class CookieUtils {//编写一个方法,返回指定名字的cookie值public static Cookie readCookieByName(String name, Cookie[] cookies) {//判断传入的参数是否正确if (name == null || "".equals(name) || cookies == null || cookies.length == 0) {return null;}//遍历cookiesfor (Cookie cookie : cookies) {if(name.equals(cookie.getName())) {return cookie;}}return null;}
}
-修改 Cookie
public class UpdateCookie extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("UpdateCookie 被调用...");//需求/*** 1. 需求 演示如何修改Cookie* 1) 给定一个cookie的name, 找到该cookie, 如果找到, 则修改该cookie的值为 -hi* 2) 如果找不到指定的cookie , 则提示, 没有该cookie*///1. 根据name 去查找 cookieString cookieName = "emailx";Cookie[] cookies = request.getCookies();//如果我们直接创建了一个同名的cookie也相当于修改Cookie userNameCookie = new Cookie("username", "hahaha");Cookie cookie = CookieUtils.readCookieByName(cookieName, cookies);if (null == cookie) {//在该浏览器没有email cookieSystem.out.println("当前访问 服务端的 浏览器没有 该cookie");} else {cookie.setValue("hi");}System.out.println("=====修改后的cookies信息=======");//2. 编写cookiefor (Cookie cookie1 : cookies) {System.out.println("cookie name= " + cookie1.getName()+ " value= " + cookie1.getValue());}//3. 给浏览器返回信息response.setContentType("text/html;charset=utf-8");//4. 如果希望我们的浏览器本地的cookie也修改,则需要使用response.addCookie(cookie);if(cookie != null) {response.addCookie(cookie);}//把 新创建的userNameCookie 重新保存到浏览器//如果 保存的userNameCookie 和已经有的cookie同名,就等价于替换.if(userNameCookie != null) {response.addCookie(userNameCookie);}PrintWriter writer = response.getWriter();writer.println("<h1>完成修改cookie的任务..</h1>");writer.flush();writer.close();}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}
}
cookie 生命周期
介绍
1. Cookie 的生命周期指的是如何管理 Cookie 什么时候被销毁(删除)
2. setMaxAge()
● 正数,表示在指定的秒数后过期
● 负数,表示浏览器关闭,Cookie 就会被删除(默认值是-1)
● 0,表示马上删除 Cookie
代码示例
public class CookieLive extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("CookieLive 被调用...");//演示创建一个cookie , 生命周期为 60sCookie cookie = new Cookie("job", "java");//解读:// 1. 从创建该cookie开始计时, 60秒后无效// 2. 浏览器来根据创建的时间,计时到60s秒,就认为该cookie无效// 3. 如果该cookie无效,那么浏览器在发出http请求时,就不在携带该cookiecookie.setMaxAge(60);//将cookie保存到浏览器response.addCookie(cookie);//演示如何删除一个cookie, 比如删除username//1 先得到username cookieCookie[] cookies = request.getCookies();Cookie usernameCookie =CookieUtils.readCookieByName("username", cookies);if(usernameCookie != null) {//2. 将其生命周期设置为0usernameCookie.setMaxAge(0);//3. 重新保存该cookie, 因为你将其生命周期设置0, 就等价于让浏览器删除该cookie//4. 说明:该cookie会被浏览器直接删除// 返回一个Set-Cookie: xxxxx => 一会抓包.// Set-Cookie: username=tom; Expires=Thu, 01-Jan-1970 00:00:10 GMTresponse.addCookie(usernameCookie);//返回一个Set-Cookie: xxxxx => 一会抓包.}else{System.out.println("没有找到该cookie, 无法删除...");}/************************ 默认的会话级别的 Cookie [即浏览器关闭就销毁了]* 前面我们讲课时,都是默认会话级别的生命周期***********************/Cookie cookie3 = new Cookie("dkey", "dkey_value");/*** 解读 setMaxAge源码* public void setMaxAge(int expiry) {* this.maxAge = expiry;* }* private int maxAge = -1; 默认就是-1*///cookie.setMaxAge(-1);//设置存活时间response.addCookie(cookie3);// 给浏览器返回信息response.setContentType("text/html;charset=utf-8");PrintWriter writer = response.getWriter();writer.println("<h1>设置cookie生命周期</h1>");writer.flush();writer.close();}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}
}
3. 完成测试 , 注意抓包看数据
cookie 有效路径
有效路径规则
1. Cookie 有效路径 Path 的设置
2. Cookie 的 path 属性可以有效的过滤哪些 Cookie 可以发送给服务器。哪些不发。path属性是通过请求的地址来进行有效的过滤
3. 规则如下:
cookie1.setPath = /工程路径
cookie2.setPath = /工程路径/aaa
请求地址: http://ip:端口/工程路径/资源
cookie1 会发给服务器
cookie2 不会发给服务器
请求地址: http://ip:端口/工程路径/aaa/资源
cookie1 会发给服务器
cookie2 会发给服务器
代码示例
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;public class CookiePathServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {Cookie cookie = new Cookie("keyPath1", "keyPath1Value");// request.getContextPath() + "/aaa" 得到 /工程路径/aaacookie.setPath(request.getContextPath() + "/aaa");Cookie cookie2 = new Cookie("keyPath2", "keyPath2Value");cookie2.setPath(request.getContextPath());response.addCookie(cookie);response.addCookie(cookie2);response.setContentType("text/html;charset=utf-8");response.getWriter().write("<h1>创建 Cookie keyPath1 路径 /工程路径/aaa </h1>");response.getWriter().write("<h1>创建 Cookie keyPath2 路径 /工程路径 </h1>");}
}
3. 完成测试 , 注意抓包看创建 Cookie 时,返回的数据
4. 完成测试 , 注意抓包看读取 Cookie 时,返回的数据
代码示例
需求: 完成自动填写登录账户应用案例 , 如果用户登录成功,则下次登录自动填写登录 账户
html页面
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>登录页面</title>
</head>
<body>
<h1>用户登录界面</h1>
<form action="#" method="post">u:<input type="text" name="username"><br/>p:<input type="password" name="pwd"><br/><input type="submit" value="登录">
</form>
</body>
</html>
java
public class LoginServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//System.out.println("LoginServlet 被调用...~~~");//1. 接收表单提交用户名和密码String username = request.getParameter("username");String pwd = request.getParameter("pwd");response.setContentType("text/html;charset=utf-8");PrintWriter writer = response.getWriter();//2. 判断是否合法if ("xxxx".equals(username) && "123456".equals(pwd)) {//将登录成功的用户名,以cookie的形式,保存到浏览器Cookie loginuserCookie = new Cookie("loginuser", username);//设置该cookie生命周期loginuserCookie.setMaxAge(3600 * 24 * 3);response.addCookie(loginuserCookie);//合法writer.println("<h1>登录OK</h1>");} else {//不合法writer.println("<h1>登录失败</h1>");}writer.flush();writer.close();}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}
}
Cookie 注意事项和细节
1. 一个 Cookie 只能标识一种信息,它至少含有一个标识该信息的名称(NAME)和设置值(VALUE)。
2. 一个 WEB 站点可以给一个浏览器发送多个 Cookie,一个浏览器也可以存储多个 WEB 站点提供的 Cookie。
3. cookie 的总数量没有限制,但是每个域名的 COOKIE 数量和每个 COOKIE 的大小是有限制的 (不同的浏览器限制不同, 知道即可) , Cookie 不适合存放数据量大的信息。
4. 注意,删除 cookie 时,path 必须一致,否则不会删除
5. Java servlet 中 cookie 中文乱码
说明 如果存放中文的 cookie, 默认报错, 可以通过 URL 编码和解码来解决, 不建议存 放中文的 cookie 信息
代码解决
设置
public class EncoderCookie extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//System.out.println("EncoderCookie 被调用");//1. 创建cookie, 有中文//1) 如果直接存放中文的cookie, 报错 Control character in cookie value or attribute.//2) 解决方法,就是将中文 编程成 URL编码 英文: Encode=编码//3) 编码后,再保存即可String company = URLEncoder.encode("大家好", "utf-8");Cookie cookie = new Cookie("company", company);//2. 保存到浏览器response.addCookie(cookie);//3. 给浏览器返回信息response.setContentType("text/html;charset=utf-8");PrintWriter writer = response.getWriter();writer.println("<h1>设置中文cookie成功</h1>");writer.flush();writer.close();}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}
}
解码
public class ReadCookie2 extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("ReadCookie2 被调用..");//读取到中文cookieCookie[] cookies = request.getCookies();Cookie companyCookie = CookieUtils.readCookieByName("company",cookies);String companyVal = companyCookie.getValue();System.out.println("companyVal= " + companyVal);//URL//解码companyVal = URLDecoder.decode(companyVal, "utf-8");System.out.println("解码后 companyVal= " + companyVal);//中文//3. 给浏览器返回信息response.setContentType("text/html;charset=utf-8");PrintWriter writer = response.getWriter();writer.println("<h1>读取中文cookie解码成功~</h1>");writer.flush();writer.close();}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request,response);}
}