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);
*/
//方式2
SimpleDateFormat 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不为null
for(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的值,名为:lastTime
Cookie 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的cookie
1
1(算法:直接返回传入的id)
1
2
2,1(没有重复且<3个
算法:直接把传入的id放最前面)
2,1
1
2,1(有重复且<3个
算法:去掉重复id,把传入的id放最前面)
2,1
3
3,2,1(没有重复<3个
算法:直接把传入的id放最前面)
3,2,1
2
3,2,1(有重复且=3个
算法:去掉重复的,把传入的id放最前面)
3,2,1
4
4,3,2(没有重复且=3个
算法:去掉最后的id,把传入的id放最前面)
商品展示Servlet
package com.cn.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
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 com.cn.dao.ProductDao;
import com.cn.entity.Product;
public class ListServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/*
* 设置响应格式
*/
response.setContentType("text/html; charset=utf-8");
/**
* 1.读取数据库,查询商品列表
*/
ProductDao dao = new ProductDao();
List<Product> list = dao.findAll();
/**
* 2.把商品显示到浏览器
*/
String html = "";
html += "<html>";
html += "<head>";
html += "<title>显示商品列表</title>";
html += "</head>";
html += "<body>";
html += "<table border='1' align='center' width='600px'>";
html += "<tr>";
html += "<th>编号</th><th>商品名称</th><th>商品型号</th><th>商品价格</th>";
html += "</tr>";
/**
* 遍历商品
*/
if(list != null){
for(Product p : list){
html += "<tr>";
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>";;
html += "</tr>";
}
}
html += "</table>";
/**
* 显示浏览过的商品
*/
html += "最近浏览过的商品<br/>";
/**
* 取出proHistory的cookie
*/
Cookie[] cookies = request.getCookies();
if(cookies != null){
for(Cookie cookie : cookies){
if("proHistory".equals(cookie.getName())){
String proHistory = cookie.getValue();//这里是cookie信息, 3,2,1
String[] ids = proHistory.split(",");
/**
* 遍历浏览过的商品id
*/
for(int i=0; i<ids.length; i++){
//查找对应的商品
Product product = dao.findById(ids[i]);
//显示到浏览器
html += "" + product.getId() + " " + product.getProName() + " " + product.getPrice() + "<br/>";
}
}
break;
}
}
html += "</body>";
html += "</html>";
response.getWriter().write(html);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
}
详情Servlet
package com.cn.servlet;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;
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 com.cn.dao.ProductDao;
import com.cn.entity.Product;
/**
* Author:Liu Zhiyong(QQ:1012421396)
* Version:Version_1
* Date:2016年12月2日19:28:05
* Desc:案例_查看用户浏览器过的商品
*/
public class DetailServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/*
* 设置响应格式
*/
response.setContentType("text/html; charset=utf-8");
/**
* 1.获取页面传递过来的编号
*/
String id = request.getParameter("id");
/**
* 2.根据编号,查询对应的商品
*/
ProductDao dao = new ProductDao();
Product product = dao.findById(id);
/**
* 3.把商品显示到浏览器
*/
String html = "";
html += "<html>";
html += "<head>";
html += "<title>显示商品的详情</title>";
html += "</head>";
html += "<body>";
html += "<table border='1' align='center' width='600px'>";
if(product != null){
html += "<tr><th>编号</th><td>" + product.getId() + "</td></tr>";
html += "<tr><th>商品名称</th><td>" + product.getProName() + "</td></tr>";
html += "<tr><th>商品型号</th><td>" + product.getProType() + "</td></tr>";
html += "<tr><th>商品价格</th><td>" + product.getPrice() + "</td></tr>";
}
html += "</table>";
html += "<center><a href='"+ request.getContextPath() +"/ListServlet'>【返回列表】</a></center>";
html += "</body>";
html += "</html>";
response.getWriter().write(html);
Cookie cookie = new Cookie("proHistory", createCookie(request, id));
cookie.setMaxAge(1*30*24*60*60);//保存一个月
response.addCookie(cookie);
}
/**
* 生成cookie的值的算法:
* 分析:
* 当前cookie的值 传入商品id 最终cookie值
* null或者没有名为proHistory的cookie 1 1(算法:直接返回传入的id)
* 1 2 2,1(没有重复且<3个 算法:直接把传入的id放最前面)
* 2,1 1 2,1(有重复且<3个 算法:去掉重复id,把传入的id放最前面)
* 2,1 3 3,2,1(没有重复<3个 算法:直接把传入的id放最前面)
* 3,2,1 2 3,2,1(有重复且=3个 算法:去掉重复的,把传入的id放最前面)
* 3,2,1 4 4,3,2(没有重复且=3个 算法:去掉最后的id,把传入的id放最前面)
* @param request
* @param id
* @return
*/
public String createCookie(HttpServletRequest request, String id) {
/**
* 首先获取所有的cookie信息
*/
Cookie[] cookies = request.getCookies();
String proHistory = null;
if(cookies != null){//如果存在cookie
// boolean flag = false;//名为proHistory的cookie是否存在标志,默认不存在
for(Cookie cookie : cookies){//遍历cookie
if("proHistory".equals(cookie.getName())){//如果cookie中有名为proHistory的cookie
//先获取cookie名为proHistory的值
proHistory = cookie.getValue();
/* //用逗号分割cookie值
String[] valueArray = proHistory.split(",");
String hisValue = "";
for(int i=0; i<valueArray.length; i++){
if(i > 1){//历史商品记录存放超过了2个,下面还会新增一个,总共cookie中放3个
break;
}
hisValue += valueArray[i] + ",";
}
*//**
* 1.添加新cookie值
*//*
cookie.setValue(id + "," + hisValue);
cookie.setMaxAge(1*30*24*60*60);//保存一个月
//2.发送cookie
response.addCookie(cookie);
flag = true;*/
break; //结束循环
}
}
}
if(cookies == null || proHistory == null){//如果不存在任何cookie,或者不存在名为proHistory的cookie
return id;
/*//创建cookie
Cookie cookie = new Cookie("proHistory", id);
cookie.setMaxAge(1*30*24*60*60);//保存一个月
//发送cookie
response.addCookie(cookie);*/
}
String[] ids = proHistory.split(",");
/*Collection<String> idList = new ArrayList<String>();
for(String item : ids){
idList.add(item);
}*/
/*
*String->Collection
*目的是为了方便判断重复id
*/
Collection<String> idList = Arrays.asList(ids);
//集合转成LinkedList 方便地操作(增删改元素)集合
LinkedList list = new LinkedList(idList);
/*
* 不超过3个的情况
*/
if(list.size() < 3){
/*
* id重复
*/
if(list.contains(id)){
//去掉重复id,把传入的id放最前面
list.remove(id);
list.addFirst(id);
}else{
//直接把传入的id放最前面
list.addFirst(id);
}
}else if(list.size() == 3){//正好3个
/*
* id重复
*/
if(list.contains(id)){
//去掉重复id,把传入的id方最前面
list.remove(id);
list.addFirst(id);
}else{
//去掉最后的id,把传入的id放最前面
list.removeLast();
list.addFirst(id);
}
}
/*
* LinkedList -> String
* 插入“,”间隔,转成String
*/
StringBuffer sb = new StringBuffer();
for(Object obj : list){
sb.append(obj + ",");
}
//最后多了一个逗号, 去除末尾的逗号
String result = sb.toString();
result = result.substring(0, result.length()-1);
return result;
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
}
dao
package com.cn.dao;
import java.util.ArrayList;
import java.util.List;
import com.cn.entity.Product;
/**
* 该类中存放了对Product对象的CRUD操作方法
*/
public class ProductDao {
/**
* 模拟数据库,存放了所有的商品数据
*/
private static List<Product> data = new ArrayList<Product>();
/**
* 初始化商品数据
*/
static{
//只执行一次
for(int i=1; i<=10; i++){
data.add(new Product(i+"", ("联想笔记本"+i), ("lenovo"+i), 2000.0*i));
}
}
/**
* 查询所有商品
* @return
*/
public List<Product> findAll(){
return data;
}
/**
* 根据提供的编号查询商品的方法
* @param id
* @return
*/
public Product findById(String id){
for(Product p : data){
if(id.equals(p.getId())){
return p;
}
}
return null;
}
}
实体对象
package com.cn.entity;
public class Product {
private String id;
private String proName;
private String proType;
private double price;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getProName() {
return proName;
}
public void setProName(String proName) {
this.proName = proName;
}
public String getProType() {
return proType;
}
public void setProType(String proType) {
this.proType = proType;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public Product() {
super();
}
public Product(String id, String proName, String proType, double price) {
super();
this.id = id;
this.proName = proName;
this.proType = proType;
this.price = price;
}
@Override
public String toString() {
return "Product [id=" + id + ", proName=" + proName + ", proType="
+ proType + ", price=" + price + "]";
}
}