基本概念: 指用户开一个浏览器,访问一个网站,只要不关闭该浏览器,不管该用户点击多少个超链接,访问多少资源,直到用户关闭浏览器,整个这个过程我们称为一次会话.
会话跟踪技术可以解决我们很多很多问题。
会话跟踪技术有Cookie和Session,Cookie技术是先出现的。我们先讲Cookie技术吧。
Cookie是由W3C组织提出,最早由netscape社区发展的一种机制
Cookie的流程:浏览器访问服务器,如果服务器需要记录该用户的状态,就使用response向浏览器发送一个Cookie,浏览器会把Cookie保存起来。当浏览器再次访问服务器的时候,浏览器会把请求的网址连同Cookie一同交给服务器。
常用的Cookie方法:
//设置response的编码
response.setContentType("text/html;charset=UTF-8");
//创建Cookie对象,指定名称和值
Cookie cookie = new Cookie("username", "zhongfucheng");
//向浏览器给一个Cookie
response.addCookie(cookie);
response.getWriter().write("我已经向浏览器发送了一个Cookie");
//设置Cookie的时间
cookie.setMaxAge(1000);
response.setContentType("text/html;charset=UTF-8");
PrintWriter printWriter = response.getWriter();
String name = "中国";
Cookie cookie = new Cookie("country", name);
cookie.setMaxAge(2000);
response.addCookie(cookie);
printWriter.write("我颁发了一个Cookie,值保存的是中文数据");
//对Unicode字符进行编码
Cookie cookie = new Cookie("country", URLEncoder.encode(name, "UTF-8"));
Cookie[] cookies = request.getCookies();
for (int i = 0; cookies != null && i < cookies.length; i++) {
String name = cookies[i].getName();
//经过URLEncoding就要URLDecoding
String value = URLDecoder.decode(cookies[i].getValue(), "UTF-8");
printWriter.write(name + "------" + value);
}
Cookie的有效期是通过setMaxAge()来设置的。
Cookie的名称相同,通过response添加到浏览器中,会覆盖原来的Cookie。
以country为名保存的是%E4%B8%AD%E5%9B%BD,下面我再以country为名,把值改变一下。
String name = "看完博客就点赞";
//对Unicode字符进行编码
Cookie cookie = new Cookie("country", URLEncoder.encode(name, "UTF-8"));
String name = "看完博客就点赞";
//对Unicode字符进行编码
Cookie cookie = new Cookie("country", URLEncoder.encode(name, "UTF-8"));
//一定不要忘记添加到浏览器中
cookie.setMaxAge(0);
response.addCookie(cookie);
printWriter.write("我删除了该Cookie");
注意:删除,修改Cookie时,新建的Cookie除了value、maxAge之外的所有属性都要与原Cookie相同。否则浏览器将视为不同的Cookie,不予覆盖,导致删除修改失败!
我们来试验一下把。
String name = "看完博客就点赞";
//对Unicode字符进行编码
Cookie cookie = new Cookie("country", URLEncoder.encode(name, "UTF-8"));
//一定不要忘记添加到浏览器中
cookie.setMaxAge(10000);
response.addCookie(cookie);
//一定不要忘记添加到浏览器中
cookie.setPath("/ouzicheng");
cookie.setMaxAge(0);
response.addCookie(cookie);
printWriter.write("删除一个Cookie");
Cookie的domain属性决定运行访问Cookie的域名。domain的值规定为“.域名”
Cookie的隐私安全机制决定Cookie是不可跨域名的。也就是说www.baidu.com和www.google.com之间的Cookie是互不交接的。即使是同一级域名,不同二级域名也不能交接,也就是说:www.goole.com和www.image.goole.com的Cookie也不能访问
我在本地上配置了3个虚拟主机,localhost,www.zhongfucheng.com,www.image.zhongfucheng.com【如果不知道怎么配置,在我Tomcat的博客有】
Cookie cookie = new Cookie("name", "zhongfucheng");
cookie.setMaxAge(1000);
response.addCookie(cookie);
printWriter.write("使用www.zhongfucheng.com域名添加了一个Cookie");
Cookie cookie = new Cookie("name", "ouzicheng");
cookie.setMaxAge(1000);
cookie.setDomain(".zhongfucheng.com");
response.addCookie(cookie);
printWriter.write("使用www.zhongfucheng.com域名添加了一个Cookie,只要一级是zhongfucheng.com即可访问");
使用www.zhongfucheng.com发布一个Cookie
使用www.image.zhongfucheng.com域名访问一下。发现可以获取到Cookie了
Cookie的path属性决定允许访问Cookie的路径
一般地,Cookie发布出来,整个网页的资源都可以使用。现在我只想Servlet1可以获取到Cookie,其他的资源不能获取。
使用Servlet2颁发一个Cookie给浏览器,设置路径为”/Servlet1”。
Cookie cookie = new Cookie("username", "java");
cookie.setPath("/Servlet1");
cookie.setMaxAge(1000);
response.addCookie(cookie);
printWriter.write("该Cookie只有Servlet1获取得到");
访问Serlvet有两种情况
全部代码如下:
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
response.setContentType("text/html;charset=UTF-8");
PrintWriter printWriter = response.getWriter();
//获取网页上所有的Cookie
Cookie[] cookies = request.getCookies();
//判断Cookie的值是否为空
String cookieValue = null;
for (int i = 0; cookies != null && i < cookies.length; i++) {
//获取到以time为名的Cookie
if (cookies[i].getName().equals("time")) {
printWriter.write("您上次登陆的时间是:");
cookieValue = cookies[i].getValue();
printWriter.write(cookieValue);
cookies[i].setValue(simpleDateFormat.format(new Date()));
response.addCookie(cookies[i]);
//既然已经找到了就可以break循环了
break;
}
}
//如果Cookie的值是空的,那么就是第一次访问
if (cookieValue == null) {
//创建一个Cookie对象,日期为当前时间
Cookie cookie = new Cookie("time", simpleDateFormat.format(new Date()));
//设置Cookie的生命期
cookie.setMaxAge(20000);
//response对象回送Cookie给浏览器
response.addCookie(cookie);
printWriter.write("您是第一次登陆啊!");
}
我们换一个逻辑写:先检查(遍历)所有Cookie有没有我要的,如果得不到我想要的Cookie,Cookie的值是null,那么就是第一次登陆,于是就有了上面的代码了。
我们来看下效果吧!当我第一次登陆的时候
private String id ;
private String name ;
private String author;
public Book() {
}
public Book(String id, String name, String author) {
this.id = id;
this.name = name;
this.author = author;
}
...各种set、get方法
private static LinkedHashMap linkedHashMap = new LinkedHashMap();
//简化开发复杂度,book的id和商品的id相同
static {
linkedHashMap.put("1", new Book("1", "javaweb", "zhong"));
linkedHashMap.put("2", new Book("2", "java", "fu"));
linkedHashMap.put("3", new Book("3", "oracle", "cheng"));
linkedHashMap.put("4", new Book("4", "mysql", "ou"));
linkedHashMap.put("5", new Book("5", "ajax", "zi"));
}
//获取到所有书籍
public static LinkedHashMap getAll() {
return linkedHashMap;
}
printWriter.write("网页上所有的书籍:"+"
");
//拿到数据库所有的书
LinkedHashMap linkedHashMap = DB.getAll();
Set > entry = linkedHashMap.entrySet();
//显示所有的书到网页上
for (Map.Entry stringBookEntry : entry) {
Book book = stringBookEntry.getValue();
printWriter.write(book.getId() +" "+ book.getName()+"
");
}
//显示所有的书到网页上
for (Map.Entry stringBookEntry : entry) {
Book book = stringBookEntry.getValue();
printWriter.write(" + book.getName() + "");
printWriter.write("
");
}
String id = request.getParameter("id");
//由于book的id和商品的id是一致的。获取到用户点击的书
Book book = (Book) DB.getAll().get(id);
//输出书的详细信息
printWriter.write("书的编号是:" + book.getId()+"
");
printWriter.write("书的名称是:" + book.getName()+"
");
printWriter.write("书的作者是:" + book.getAuthor()+"
");
既然用户点击了书籍,那么服务器就应该颁发Cookie给浏览器,记住用户点击了该书籍
现在问题来了,Cookie的值应该是什么呢?试想一下,待会还要把浏览过的书籍显示出来,所以用书籍的id是最好不过的。想到了用书籍的id作为Cookie的值,我们还要定义一些规则!
书籍的id都是数字,如果不做任何修改,存到Cookie里边可能就是231,345,123此类的数字,这样取出某一个id的时候就十分费劲并且后面还要判断该书是否存在Cookie里边了,所以我们要把存储到Cookie的书籍id分割起来。所以我们定义”_“作为分隔符
按上面的应用,我们的逻辑应该是:先遍历下Cookie,看下有没有我们想要的Cookie。如果找到想要的Cookie,那就取出Cookie的值
String bookHistory = null;
Cookie[] cookies = request.getCookies();
for (int i = 0; cookies != null && i < cookies.length; i++) {
if (cookies[i].getName().equals("bookHistory")) {
bookHistory = cookies[i].getValue();
}
}
取出了Cookie的值也分几种情况
if (bookHistory == null) {
return id;
}
//如果Cookie的值不是null的,那么就分解Cookie的得到之前的id。
String[] strings = bookHistory.split("\\_");
//为了增删容易并且还要判断id是否存在于该字符串内-----我们使用LinkedList集合装载分解出来的id
List list = Arrays.asList(strings);
LinkedList linkedList = new LinkedList<>();
linkedList.addAll(list);
if (linkedList.contains(id)) {
linkedList.remove(id);
linkedList.addFirst(id);
}else {
if (linkedList.size() >= 3) {
linkedList.removeLast();
linkedList.addFirst(id);
} else {
linkedList.addFirst(id);
}
}
StringBuffer stringBuffer = new StringBuffer();
//遍历LinkedList集合,添加个下划线“_”
for (String s : linkedList) {
stringBuffer.append(s + "_");
}
//最后一个元素后面就不需要下划线了
return stringBuffer.deleteCharAt(stringBuffer.length() - 1).toString();
String bookHistory = makeHistory(request, id);
Cookie cookie = new Cookie("bookHistory", bookHistory);
cookie.setMaxAge(30000);
response.addCookie(cookie);
printWriter.write("您曾经浏览过的商品:");
printWriter.write("
");
//显示用户浏览过的商品
Cookie[] cookies = request.getCookies();
for (int i = 0; cookies != null && i < cookies.length; i++) {
if (cookies[i].getName().equals("bookHistory")) {
//获取到的bookHistory是2_3_1之类的
String bookHistory = cookies[i].getValue();
//拆解成每一个id值
String[] ids = bookHistory.split("\\_");
//得到每一个id值
for (String id : ids) {
//通过id找到每一本书
Book book = linkedHashMap.get(id);
printWriter.write(book.getName());
printWriter.write("
");
}
break;
}
}