Cookie

来源:互联网 发布:世界线收束 知乎 编辑:程序博客网 时间:2024/04/25 16:05
Cookie技术核心

Cookie类:用于存储会话数据

1)构造Cookie对象
Cookie(java.lang.String name, java.lang.String value)
2)设置cookie
void setPath(java.lang.String uri)   :设置cookie的有效访问路径
void setMaxAge(int expiry) : 设置cookie的有效时间
void setValue(java.lang.String newValue) :设置cookie的值
3)发送cookie到浏览器端保存
void response.addCookie(Cookie cookie)  : 发送cookie
4)服务器接收cookie
Cookie[] request.getCookies()  : 接收cookie

Cookie原理
1)服务器创建cookie对象,把会话数据存储到cookie对象中。
new Cookie("name","value");
2)服务器发送cookie信息到浏览器(隐藏发送了一个set-cookie名称的响应头,通过响应头发送:set-cookie:name1=value1,name2=value2)
response.setHeader("set-cookie", "myname=Mary,mypass=1234");//注意这里添加多个cookie,必须用逗号间隔
但是推荐使用下面这种方式:避免手动去发送cookie信息
response.addCookie(cookie);
3)浏览器得到服务器发送的cookie,然后保存在浏览器端。
4)浏览器在下次访问服务器时,会带着cookie信息
举例: cookie: name1=value1;name2=value2  (隐藏带着一个叫cookie名称的请求头)
5)服务器接收到浏览器带来的cookie信息
String name = request.getHeader("cookie");
但是推荐使用下面面向对象的方式
request.getCookies();

Cookie的细节
1)void setPath(java.lang.String uri)   :设置cookie的有效访问路径。默认情况:有效路径在当前web应用下。有效路径指的是cookie的有效路径保存在哪里,那么浏览器在有效路径下访问服务器时就会带着cookie信息,否则不带cookie信息,注意:在获取cookie的name和value之前判断cookie是否为空,否则会出现空指针异常。

2)void setMaxAge(int expiry) : 设置cookie的有效时间。
正整数:表示cookie数据保存浏览器的缓存目录(硬盘中,不会因为浏览器的关闭而影响时间),数值表示保存的时间,单位是秒,从最后一次发送cookie到浏览器的时间开始计算。
负整数:表示cookie数据保存浏览器的内存中。浏览器关闭cookie就丢失了!!(会话cookie)
0:表示删除同名的cookie数据。
例如:
Cookie cookie = new Cookie("username", "zhe li bi xu shi fei zhong wen");//注意:这里cookie里面的值必须是非中文,随便什么值即可。
cookie.setMaxAge(0);//删除同名的cookie
response.addCookie(cookie);
System.out.println("删除成功");
3)Cookie数据类型只能保存非中文字符串类型的。可以保存多个cookie,但是浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4KB。

Demo:
package com.cn.cookie;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.http.Cookie;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class CookieDemo1 extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {this.doPost(request, response);}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {/* * 1.创建Cookie对象 */Cookie cookie1 = new Cookie("username", "lzy");//Cookie cookie2 = new Cookie("password", "666666");/* * 1.1)设置cookie的有效路径。默认情况:有效路径在当前web应用下(/test) * 注意:这里设置cookie的有效访问路径,应该在cookie数据发送到浏览器之前 设置。 */cookie1.setPath("/test");//cookie2.setPath("/test2");/* * 1.2)设置cookie的有效时间。正整数:表示cookie数据保存浏览器的缓存目录(硬盘中,不会因为浏览器的关闭而影响时间),数值表示保存的时间,单位是秒。负整数:表示cookie数据保存浏览器的内存中。浏览器关闭cookie就丢失了!!(会话cookie)0:表示删除同名的cookie数据 *///cookie1.setMaxAge(20);//20秒,从最后一次调用cookie开始计算,即使浏览器关闭,如果还在20秒范围内,cookie还有效。保存在硬盘中。//cookie1.setMaxAge(-1);//cookie保存在浏览器内存(会话cookie)。浏览器关闭,cookie丢失cookie1.setMaxAge(-1);/* * 2.把cookie数据发送到浏览器(通过响应头发送:set-cookie名称) *///response.setHeader("set-cookie", "myname=Mary,mypass=1234");//注意这里添加多个cookie,必须用逗号间隔/* * 推荐使用这种方式:避免手动去发送cookie信息 */response.addCookie(cookie1);//response.addCookie(cookie2);/* * 3.接收浏览器发送的cookie信息 *///String name = request.getHeader("cookie");//System.out.println(name);Cookie[] cookies = request.getCookies();//注意:判断是否为null,否则空指针异常if(cookies != null){for(Cookie cookie : cookies){System.out.println(cookie.getName() + "=" + cookie.getValue());}}else{System.out.println("没有接收到cookie数据");}}}


Cookie案例1:显示用户上次访问的时间
需求:
如果第一次访问本网站,则显示“您是首次访问本网站,当前时间为2016-12-1 09:00:21”
如果是第n次本网站,则显示“欢迎回来,您上次访问的时间为:2016-12-1 09:01:11,当前时间为2016-12-1 09:01:18”
package com.cn.cookie;import java.io.IOException;import java.text.SimpleDateFormat;import java.util.Calendar;import java.util.Date;import java.util.logging.SimpleFormatter;import javax.servlet.ServletException;import javax.servlet.http.Cookie;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/*** Author:Liu Zhiyong(QQ:1012421396)* Version:Version_1* Date:2016年12月1日09:01:40* Desc:Cookie案例:显示用户上次访问的时间需求:如果第一次访问本网站,则显示“您是首次访问本网站,当前时间为2016-12-1 09:00:21”如果是第n次本网站,则显示“欢迎回来,您上次访问的时间为:2016-12-1 09:01:11,当前时间为2016-12-1 09:01:18”*/public class HistoryServlet extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {this.doPost(request, response);}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {response.setContentType("text/html; charset=utf-8");/* * 获取当前时间 *///方式1/*Calendar calendar = Calendar.getInstance();String currentTime = calendar.get(Calendar.YEAR) + "-" + (calendar.get(Calendar.MONTH)+1) + "-" + calendar.get(Calendar.DATE) + " " + calendar.get(Calendar.HOUR) + ":" + calendar.get(Calendar.MINUTE) + ":" + calendar.get(Calendar.SECOND); *///方式2SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");String currentTime = sdf.format(new Date());/* * 首先获取cookie中是否存在name="lastTime" */Cookie[] cookies = request.getCookies();String lastTime = null;if(cookies != null){//如果cookie不为nullfor(Cookie cookie : cookies){String name = cookie.getName();if("lastTime".equals(name)){//获取cookie的name,判断是否为你设置的lastTime//获取cookie的值(上次访问时间)lastTime = cookie.getValue();//1 把上次保存的时间显示到上次访问时间到浏览器response.getWriter().write("欢迎回来,您上次访问的时间为:" + lastTime + " 当前时间为:" + currentTime);//2 更新名为lastTime的cookie,值设置为当前时间 cookie.setValue(currentTime);cookie.setMaxAge(1*30*24*60*60);//保存一个月//3 把更新后的cookie发送给浏览器保存response.addCookie(cookie);break;//退出循环}}}/* * 第一次访问(没有cookie或者有cookie,但是没有名为lastTime的cookie) */if(cookies == null || lastTime == null){//1 显示当前时间到浏览器response.getWriter().write("您是首次访问本网站,当前时间为:" + currentTime);//2 创建Cookie对象,时间作为cookie的值,名为:lastTimeCookie cookie = new Cookie("lastTime", currentTime);cookie.setMaxAge(1*30*24*60*60);//保存一个月//3 把cookie发送到浏览器保存response.addCookie(cookie);}}}

Cookie案例2:查看用户浏览器过的商品
    需求:浏览过的商品,显示出来,不超过3个
    分析:


生成cookie的值的算法:
  分析:
当前cookie的值         传入商品id最终cookie值
null或者没有名为proHistory的cookie1 1(算法:直接返回传入的id)
1                        22,1(没有重复且<3个算法:直接把传入的id放最前面)
2,1                        12,1(有重复且<3个         算法:去掉重复id,把传入的id放最前面)
2,1                        33,2,1(没有重复<3个算法:直接把传入的id放最前面)
3,2,1                        23,2,1(有重复且=3个算法:去掉重复的,把传入的id放最前面)
3,2,1                        44,3,2(没有重复且=3个         算法:去掉最后的id,把传入的id放最前面)
商品展示Servlet
  1. package com.cn.servlet;
  2. import java.io.IOException;
  3. import java.io.PrintWriter;
  4. import java.util.List;
  5. import javax.servlet.ServletException;
  6. import javax.servlet.http.Cookie;
  7. import javax.servlet.http.HttpServlet;
  8. import javax.servlet.http.HttpServletRequest;
  9. import javax.servlet.http.HttpServletResponse;
  10. import com.cn.dao.ProductDao;
  11. import com.cn.entity.Product;
  12. public class ListServlet extends HttpServlet {
  13. public void doGet(HttpServletRequest request, HttpServletResponse response)
  14. throws ServletException, IOException {
  15. /*
  16. * 设置响应格式
  17. */
  18. response.setContentType("text/html; charset=utf-8");
  19. /**
  20. * 1.读取数据库,查询商品列表
  21. */
  22. ProductDao dao = new ProductDao();
  23. List<Product> list = dao.findAll();
  24. /**
  25. * 2.把商品显示到浏览器
  26. */
  27. String html = "";
  28. html += "<html>";
  29. html += "<head>";
  30. html += "<title>显示商品列表</title>";
  31. html += "</head>";
  32. html += "<body>";
  33. html += "<table border='1' align='center' width='600px'>";
  34. html += "<tr>";
  35. html += "<th>编号</th><th>商品名称</th><th>商品型号</th><th>商品价格</th>";
  36. html += "</tr>";
  37. /**
  38. * 遍历商品
  39. */
  40. if(list != null){
  41. for(Product p : list){
  42. html += "<tr>";
  43. html += "<td>" + p.getId() + "</td><td><a href='" + request.getContextPath() + "/DetailServlet?id=" + p.getId() + "'>" +p.getProName() + "</a></td><td>" + p.getProType() + "</td><td>" + p.getPrice() + "</td>";;
  44. html += "</tr>";
  45. }
  46. }
  47. html += "</table>";
  48. /**
  49. * 显示浏览过的商品
  50. */
  51. html += "最近浏览过的商品<br/>";
  52. /**
  53. * 取出proHistory的cookie
  54. */
  55. Cookie[] cookies = request.getCookies();
  56. if(cookies != null){
  57. for(Cookie cookie : cookies){
  58. if("proHistory".equals(cookie.getName())){
  59. String proHistory = cookie.getValue();//这里是cookie信息, 3,2,1
  60. String[] ids = proHistory.split(",");
  61. /**
  62. * 遍历浏览过的商品id
  63. */
  64. for(int i=0; i<ids.length; i++){
  65. //查找对应的商品
  66. Product product = dao.findById(ids[i]);
  67. //显示到浏览器
  68. html += "" + product.getId() + "&nbsp;" + product.getProName() + "&nbsp;" + product.getPrice() + "<br/>";
  69. }
  70. }
  71. break;
  72. }
  73. }
  74. html += "</body>";
  75. html += "</html>";
  76. response.getWriter().write(html);
  77. }
  78. public void doPost(HttpServletRequest request, HttpServletResponse response)
  79. throws ServletException, IOException {
  80. this.doGet(request, response);
  81. }
  82. }
详情Servlet
  1. package com.cn.servlet;
  2. import java.io.IOException;
  3. import java.util.Arrays;
  4. import java.util.Collection;
  5. import java.util.LinkedList;
  6. import javax.servlet.ServletException;
  7. import javax.servlet.http.Cookie;
  8. import javax.servlet.http.HttpServlet;
  9. import javax.servlet.http.HttpServletRequest;
  10. import javax.servlet.http.HttpServletResponse;
  11. import com.cn.dao.ProductDao;
  12. import com.cn.entity.Product;
  13. /**
  14. * Author:Liu Zhiyong(QQ:1012421396)
  15. * Version:Version_1
  16. * Date:2016年12月2日19:28:05
  17. * Desc:案例_查看用户浏览器过的商品
  18. */
  19. public class DetailServlet extends HttpServlet {
  20. public void doGet(HttpServletRequest request, HttpServletResponse response)
  21. throws ServletException, IOException {
  22. /*
  23. * 设置响应格式
  24. */
  25. response.setContentType("text/html; charset=utf-8");
  26. /**
  27. * 1.获取页面传递过来的编号
  28. */
  29. String id = request.getParameter("id");
  30. /**
  31. * 2.根据编号,查询对应的商品
  32. */
  33. ProductDao dao = new ProductDao();
  34. Product product = dao.findById(id);
  35. /**
  36. * 3.把商品显示到浏览器
  37. */
  38. String html = "";
  39. html += "<html>";
  40. html += "<head>";
  41. html += "<title>显示商品的详情</title>";
  42. html += "</head>";
  43. html += "<body>";
  44. html += "<table border='1' align='center' width='600px'>";
  45. if(product != null){
  46. html += "<tr><th>编号</th><td>" + product.getId() + "</td></tr>";
  47. html += "<tr><th>商品名称</th><td>" + product.getProName() + "</td></tr>";
  48. html += "<tr><th>商品型号</th><td>" + product.getProType() + "</td></tr>";
  49. html += "<tr><th>商品价格</th><td>" + product.getPrice() + "</td></tr>";
  50. }
  51. html += "</table>";
  52. html += "<center><a href='"+ request.getContextPath() +"/ListServlet'>【返回列表】</a></center>";
  53. html += "</body>";
  54. html += "</html>";
  55. response.getWriter().write(html);
  56. Cookie cookie = new Cookie("proHistory", createCookie(request, id));
  57. cookie.setMaxAge(1*30*24*60*60);//保存一个月
  58. response.addCookie(cookie);
  59. }
  60. /**
  61. * 生成cookie的值的算法:
  62. * 分析:
  63. * 当前cookie的值传入商品id最终cookie值
  64. * null或者没有名为proHistory的cookie11(算法:直接返回传入的id)
  65. * 122,1(没有重复且<3个算法:直接把传入的id放最前面)
  66. * 2,112,1(有重复且<3个算法:去掉重复id,把传入的id放最前面)
  67. * 2,133,2,1(没有重复<3个算法:直接把传入的id放最前面)
  68. * 3,2,123,2,1(有重复且=3个算法:去掉重复的,把传入的id放最前面)
  69. * 3,2,144,3,2(没有重复且=3个算法:去掉最后的id,把传入的id放最前面)
  70. * @param request
  71. * @param id
  72. * @return
  73. */
  74. public String createCookie(HttpServletRequest request, String id) {
  75. /**
  76. * 首先获取所有的cookie信息
  77. */
  78. Cookie[] cookies = request.getCookies();
  79. String proHistory = null;
  80. if(cookies != null){//如果存在cookie
  81. //boolean flag = false;//名为proHistory的cookie是否存在标志,默认不存在
  82. for(Cookie cookie : cookies){//遍历cookie
  83. if("proHistory".equals(cookie.getName())){//如果cookie中有名为proHistory的cookie
  84. //先获取cookie名为proHistory的值
  85. proHistory = cookie.getValue();
  86. /*//用逗号分割cookie值
  87. String[] valueArray = proHistory.split(",");
  88. String hisValue = "";
  89. for(int i=0; i<valueArray.length; i++){
  90. if(i > 1){//历史商品记录存放超过了2个,下面还会新增一个,总共cookie中放3个
  91. break;
  92. }
  93. hisValue += valueArray[i] + ",";
  94. }
  95. *//**
  96. * 1.添加新cookie值
  97. *//*
  98. cookie.setValue(id + "," + hisValue);
  99. cookie.setMaxAge(1*30*24*60*60);//保存一个月
  100. //2.发送cookie
  101. response.addCookie(cookie);
  102. flag = true;*/
  103. break; //结束循环
  104. }
  105. }
  106. }
  107. if(cookies == null || proHistory == null){//如果不存在任何cookie,或者不存在名为proHistory的cookie
  108. return id;
  109. /*//创建cookie
  110. Cookie cookie = new Cookie("proHistory", id);
  111. cookie.setMaxAge(1*30*24*60*60);//保存一个月
  112. //发送cookie
  113. response.addCookie(cookie);*/
  114. }
  115. String[] ids = proHistory.split(",");
  116. /*Collection<String> idList = new ArrayList<String>();
  117. for(String item : ids){
  118. idList.add(item);
  119. }*/
  120. /*
  121. *String->Collection
  122. *目的是为了方便判断重复id
  123. */
  124. Collection<String> idList = Arrays.asList(ids);
  125. //集合转成LinkedList方便地操作(增删改元素)集合
  126. LinkedList list = new LinkedList(idList);
  127. /*
  128. * 不超过3个的情况
  129. */
  130. if(list.size() < 3){
  131. /*
  132. * id重复
  133. */
  134. if(list.contains(id)){
  135. //去掉重复id,把传入的id放最前面
  136. list.remove(id);
  137. list.addFirst(id);
  138. }else{
  139. //直接把传入的id放最前面
  140. list.addFirst(id);
  141. }
  142. }else if(list.size() == 3){//正好3个
  143. /*
  144. * id重复
  145. */
  146. if(list.contains(id)){
  147. //去掉重复id,把传入的id方最前面
  148. list.remove(id);
  149. list.addFirst(id);
  150. }else{
  151. //去掉最后的id,把传入的id放最前面
  152. list.removeLast();
  153. list.addFirst(id);
  154. }
  155. }
  156. /*
  157. * LinkedList -> String
  158. * 插入“,”间隔,转成String
  159. */
  160. StringBuffer sb = new StringBuffer();
  161. for(Object obj : list){
  162. sb.append(obj + ",");
  163. }
  164. //最后多了一个逗号, 去除末尾的逗号
  165. String result = sb.toString();
  166. result = result.substring(0, result.length()-1);
  167. return result;
  168. }
  169. public void doPost(HttpServletRequest request, HttpServletResponse response)
  170. throws ServletException, IOException {
  171. this.doGet(request, response);
  172. }
  173. }
dao
  1. package com.cn.dao;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import com.cn.entity.Product;
  5. /**
  6. * 该类中存放了对Product对象的CRUD操作方法
  7. */
  8. public class ProductDao {
  9. /**
  10. * 模拟数据库,存放了所有的商品数据
  11. */
  12. private static List<Product> data = new ArrayList<Product>();
  13. /**
  14. * 初始化商品数据
  15. */
  16. static{
  17. //只执行一次
  18. for(int i=1; i<=10; i++){
  19. data.add(new Product(i+"", ("联想笔记本"+i), ("lenovo"+i), 2000.0*i));
  20. }
  21. }
  22. /**
  23. * 查询所有商品
  24. * @return
  25. */
  26. public List<Product> findAll(){
  27. return data;
  28. }
  29. /**
  30. * 根据提供的编号查询商品的方法
  31. * @param id
  32. * @return
  33. */
  34. public Product findById(String id){
  35. for(Product p : data){
  36. if(id.equals(p.getId())){
  37. return p;
  38. }
  39. }
  40. return null;
  41. }
  42. }
实体对象
  1. package com.cn.entity;
  2. public class Product {
  3. private String id;
  4. private String proName;
  5. private String proType;
  6. private double price;
  7. public String getId() {
  8. return id;
  9. }
  10. public void setId(String id) {
  11. this.id = id;
  12. }
  13. public String getProName() {
  14. return proName;
  15. }
  16. public void setProName(String proName) {
  17. this.proName = proName;
  18. }
  19. public String getProType() {
  20. return proType;
  21. }
  22. public void setProType(String proType) {
  23. this.proType = proType;
  24. }
  25. public double getPrice() {
  26. return price;
  27. }
  28. public void setPrice(double price) {
  29. this.price = price;
  30. }
  31. public Product() {
  32. super();
  33. }
  34. public Product(String id, String proName, String proType, double price) {
  35. super();
  36. this.id = id;
  37. this.proName = proName;
  38. this.proType = proType;
  39. this.price = price;
  40. }
  41. @Override
  42. public String toString() {
  43. return "Product [id=" + id + ", proName=" + proName + ", proType="
  44. + proType + ", price=" + price + "]";
  45. }
  46. }
效果:




1 0