什么是会话?会话可以简单的理解为:用户开一个浏览器,点击多个超链接,访问服务器多个Web资源,然后关闭浏览器,整个过程称之为会话。
Cookie是客户端技术,程序把每个用户的数据以Cookie的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的Web资源时,就会带着各自的数据去。这样,Web资源处理的就是用户各自的数据了。
javax.servlet.http.Cookie类用于创建一个Cookie,在response接口中也定义一个addCookie方法,它用于在其响应头中增加一个相应的Set-Cookie头字段。同样,request接口中也定义了一个getCookies方法,它用于获取客户端中提交的所有Cookie信息。
Cookie类的常用方法:
/servlet/ServletDemo01
,在ServletDemo01中设置返回Cookie,则该Cookie的默认有效路径为 /servlet,即当用户访问 /servlet 下的Servlet时,浏览器才会发送Cookie过去。 删除cookie时,path必须一致,否则不会删除。
示例:
CookieDemo1.java
package com.wm103.cookie;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
/**
* Created by DreamBoy on 2017/5/1.
*/
/**
* 通过Cookie技术显示用户上次访问时间
*/
@WebServlet(name = "CookieDemo1", urlPatterns = {"/CookieDemo1"})
public class CookieDemo1 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 {
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.print("清除上次访问时间
");
out.print("您上次访问的时间是:");
// 获取用户的Cookie
Cookie[] cookies = request.getCookies();
for (int i = 0; cookies != null && i < cookies.length; i++) {
if(cookies[i].getName().equals("LastAccessTime")) {
long cookieValue = Long.parseLong(cookies[i].getValue());// 得到了用户的上次访问时间
Date date = new Date(cookieValue);
out.print(date.toLocaleString());
}
}
// 给用户回送最新的访问时间
Cookie cookie = new Cookie("LastAccessTime", System.currentTimeMillis() + "");
cookie.setMaxAge(30 * 24 * 3600);
cookie.setPath("/day07/");
response.addCookie(cookie);
}
}
CookieDemo2.java
package com.wm103.cookie;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Created by DreamBoy on 2017/5/1.
*/
@WebServlet(name = "CookieDemo2", urlPatterns = {"/CookieDemo2"})
public class CookieDemo2 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("LastAccessTime", System.currentTimeMillis() + "");
cookie.setMaxAge(0);
cookie.setPath("/day07/"); // 删除cookie时,path必须一致,否则不会删除
response.addCookie(cookie);
}
}
这里使用Db类模拟数据库中存储的商品信息,并以静态代码块的方式初始化集合中保存的商品信息。
CookieDemo3.java
package com.wm103.cookie;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Created by DreamBoy on 2017/5/1.
*/
/**
* 代表首页的servlet
*/
@WebServlet(name = "CookieDemo3", urlPatterns = {"/CookieDemo3"})
public class CookieDemo3 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 {
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
// 1. 输出网站所有商品
out.print("");
out.write("本网站有如下商品:
");
out.print(""
);
Map map = Db.getAll();
for (Map.Entry entry: map.entrySet()) {
Book book = entry.getValue();
out.print("" + book.getName() + "");
}
out.print("");
out.print(" ");
// 2. 显示用户曾经看过的商品
out.print("");
out.write("最近您浏览过的商品:
");
out.print(""
);
Cookie[] cookies = request.getCookies();
for (int i = 0; cookies != null && i < cookies.length; i++) {
if(cookies[i].getName().equals("BookHistory")) {
String[] ids = cookies[i].getValue().split("#"); // 以 # 分隔
for (String id: ids) {
Book book = Db.getAll().get(id);
out.print("" + book.getName() + "");
}
}
}
out.print("");
out.print("");
}
}
class Db {
private static Map map = new LinkedHashMap<>();
static { // 静态代码块
map.put("1", new Book("1", "JavaWeb开发", "007号", "一本关于JavaWeb开发的书"));
map.put("2", new Book("2", "JDBC开发", "008号", "一本关于JDBC开发的书"));
map.put("3", new Book("3", "Spring开发", "009号", "一本关于Spring开发的书"));
map.put("4", new Book("4", "Struts开发", "010号", "一本关于Struts开发的书"));
map.put("5", new Book("5", "Android开发", "011号", "一本关于Android开发的书"));
}
public static Map getAll() {
return map;
}
}
class Book {
private String id;
private String name;
private String author;
private String description;
public Book() {
}
public Book(String id, String name, String author, String description) {
this.id = id;
this.name = name;
this.author = author;
this.description = description;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
注意点:1. 记录商品浏览信息时,要求记录的所有浏览记录条数不能超过预设的长度,如果超出将删除掉最旧的记录信息。2. 访问商品后,发现商品已在保存在浏览记录中,则应调整该商品在浏览记录中的位置,将该商品的浏览记录设置为最新。
CookieDemo4.java
package com.wm103.cookie;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
/**
* Created by DreamBoy on 2017/5/1.
*/
/**
* 显示商品详细信息的Servlet
*/
@WebServlet(name = "CookieDemo4", urlPatterns = {"/CookieDemo4"})
public class CookieDemo4 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 {
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
// 1. 根据用户带过来的ID,显示相应的商品详细信息
String id = request.getParameter("id");
Book book = Db.getAll().get(id);
out.print("");
out.write(""
+ book.getName() + "-" + book.getAuthor() + "");
out.print("编号:"
+ book.getId() + "");
out.print("名称:"
+ book.getName() + "");
out.print("作者:"
+ book.getAuthor() + "");
out.print("描述:"
+ book.getDescription() + "");
out.print("");
// 2. 构建cookie,回写给浏览器
// String val = buildCookieVal(id, request);
String val = buildCookie(id, request);
Cookie cookie = new Cookie("BookHistory", val);
cookie.setMaxAge(3600 * 24 * 30);
cookie.setPath("/day07/");
response.addCookie(cookie);
}
/**
* 方法一:
* @param id
* @param request
* @return
*/
private String buildCookie(String id, HttpServletRequest request) {
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();
break;
}
}
if(bookHistory == null) {
return id;
}
int maxLen = 3;
LinkedList list = new LinkedList<>(Arrays.asList(bookHistory.split("#")));
if(list.contains(id)) {
list.remove(id);
} else {
if(list.size() >= maxLen) {
list.removeLast();
}
}
list.addFirst(id);
StringBuffer sb = new StringBuffer();
for (String bid: list) {
sb.append(bid + "#");
}
return sb.deleteCharAt(sb.length() - 1).toString();
}
/**
* 方法二:
* @param id
* @param request
* @return
*/
private String buildCookieVal(String id, HttpServletRequest request) {
Cookie[] cookies = request.getCookies();
Cookie bookHistory = null;
for(int i = 0; cookies != null && i < cookies.length; i++) {
if(cookies[i].getName().equals("BookHistory")) {
bookHistory = cookies[i];
break;
}
}
// 1. 未存在cookie记录
if(bookHistory == null) {
return id;
}
// 2. 存在cookie记录
// 2.1 检测Cookie中的ID个数是否大于或等于设置的最大存储个数
int maxLen = 3;
String[] ids = bookHistory.getValue().split("#");
List list = new ArrayList<>(Arrays.asList(ids));
if(ids.length >= maxLen) {
list = list.subList(0, maxLen - 1);
}
// 2.2 判断将要保存到Cookie的ID是否已经在已有的Cookie中存在
int pos = list.indexOf(id);
if(pos != -1) {
list.remove(pos);
}
list.add(0, id);
// 2.3 返回Cookie保存的IDs
boolean isFirst = true;
String res = "";
for (String strId :list) {
if(!isFirst) {
res += "#";
} else {
isFirst = false;
}
res += strId;
}
return res;
}
}
注意:使用“,”分隔保存商品ID,设置Cookie时,可能会发生如下错误:
java.lang.IllegalArgumentException: An invalid character [44] was present in the Cookie value
因此,这里采用“#”对商品ID进行分隔保存。