Servlet的Cookie和HttpSession
1.会话概述
什么是会话?
如同打电话
会话解决的问题?
保持各个客户端自己的数据
2.Cookie
1.Cookie的定义
2.Cookie的主要方法
注意以下几点
name: 名称不能唯一确定一个cookie。路径可能不同
value: 不能存中文
path: 默认是写入cookie那个应用的访问路径
如:http://localhost:8080/day10/servlet/cookieDemo1
Path: /day10/servlet/
当客户端访问服务器其它资源时,根据访问路径来决定是否带着cookie到服务器
当访问的路径是以cookie中path开头的路径,就带cookie,否则就不带。
maxAge: cookie的保存时间。默认是-1(表示保存在浏览器的内存中)。单位是秒
负数:cookie存在浏览器的内存中。
0:删除。路径要保持一致,否则会删错了。
正数:缓存(持久化到磁盘中)的时间。
Demo1Cookie设置最后访问时间
1 response.setContentType("text/html; charset = UTF-8"); 2 PrintWriter out = response.getWriter(); 3 //得到Cookie,输出上次的访问时间,第一次访问是没有的 4 Cookie[] cookies = request.getCookies(); 5 for (int i = 0; cookies != null && i < cookies.length; i++) { 6 if(cookies[i].getName().equals("lastAccessTime")){ 7 out.write("你最后的访问时间为"+cookies[i].getValue()); 8 } 9 } 10 //设置本次访问时间到Cookie 11 //设置清除cookie 12 out.print("<a href='"+request.getContextPath()+"/servlet/CookieDemo2'>clear</a>"); 13 //得到当前时间,创建cookie 14 SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss"); 15 String time = sdf.format(new Date()); 16 Cookie lck = new Cookie("lastAccessTime", time); 17 //设置最大时间 18 lck.setMaxAge(60*5); 19 //设置可访问的路径 20 lck.setPath(request.getContextPath()); 21 //添加cookie到浏览器 22 response.addCookie(lck);
清除Cookie的Servlet
清除Cookie其实就是设置Cookie的MaxAge为0,但是要注意:Path必须是和你要设置的Cookie相同,否则Cookie来自不同路径同名属于不同的Cookie
Cookie ck = new Cookie("lastAccessTime", ""); //设置cookie存活时间 秒 ck.setMaxAge(0); //设置cookie的路径,决定哪些路径会带着这个cookie ck.setPath(request.getContextPath()); //添加 response.addCookie(ck);
Demo2历史记录的案例
原理:
如图,当你浏览一本书的时候,还设置了一次Cookie,如果以前没有历史记录,那么创建一个Cookie放历史记录,否则,修改原有Cookie,根据一定的规则,增加Cookie中id的排列规则(这里用'-'用作分隔符号让字符串去切割).所有商品中的历史信息会读取响应的Cookie,如果有,那么读取到,切割id,遍历,查询,输出书名字。
原理大概如此上代码:
ShowAllBooks:
1 response.setContentType("text/html; charset=UTF-8"); 2 PrintWriter out = response.getWriter(); 3 Map<String, Book> map = Utils.getAllBook(); 4 out.write("所有的书<br/>"); 5 //遍历map 6 for (Map.Entry<String, Book> book : map.entrySet()) { 7 out.write("<a href='"+request.getContextPath()+"/servlet/BookDetails?id="+book.getKey()+"',target='blank'>"+book.getValue().getName()+"</a><br>"); 8 } 9 out.write("浏览历史<br/>"); 10 //遍历cookie 11 Cookie[] cookies = request.getCookies(); 12 for (int i = 0; cookies!=null && i < cookies.length; i++) { 13 if(cookies[i].getName().equals("history")) { 14 String[] s = cookies[i].getValue().split("-"); 15 for (int j = s.length; j >= 0 ; j--) { 16 out.write(Utils.getMapById(s[j]).getName()+"<br/>"); 17 } 18 } 19 }
ShowBooksDetail:
1 public void doGet(HttpServletRequest request, HttpServletResponse response) 2 throws ServletException, IOException { 3 //逻辑:获取到发送过来的id,对它进行处理成一个字符串以-连接代表历史记录的顺序 4 response.setContentType("text/html; charset=UTF-8"); 5 PrintWriter out = response.getWriter(); 6 String id = request.getParameter("id"); 7 out.write(Utils.getMapById(id).toString()); 8 Cookie history = new Cookie("history", getCookie(request, id)); 9 response.addCookie(history); 10 } 11 //根据id和request来获取 12 public String getCookie(HttpServletRequest request, String id) { 13 Cookie[] cookies = request.getCookies(); 14 if(cookies == null) { 15 return id; 16 } 17 18 String s = null; 19 // 装入字符串 20 for (int i = 0; i < cookies.length; i++) { 21 if(cookies[i].getName().equals("history")){ 22 s = cookies[i].getValue(); 23 } 24 } 25 26 if(s == null){ 27 return id; 28 } 29 //分解 30 String[] arr = s.split("-"); 31 //装入list 32 List<String> list = new ArrayList<String>(Arrays.asList(arr)); 33 //如果包含id,那么移除 34 if(s.contains(id)){ 35 list.remove(id); 36 } else { 37 if(list.size()<3) { 38 39 } else { 40 list.remove(0); 41 } 42 } 43 list.add(id); 44 //最后装入StringBuffer再转换成数组 45 StringBuffer sb = new StringBuffer(); 46 for (int i = 0; i < list.size(); i++) { 47 if(i>0) { 48 sb.append("-"); 49 } 50 sb.append(list.get(i)); 51 } 52 53 return sb.toString(); 54 }
中间的字符串处理部分可能有点复杂,可以优化。但是也算完成了,没有给Cookie加入过时的时间,所以浏览器关闭就被清理了。
3.HttpSession
1、HttpSession的定义
主要方法:
void setAttribute(String name,Object value); //设置Session的值
Object getAttribute(String name); //得到Session
void removeAttribute(String name); //删除指定的值
HttpSession.getId(): //得到Id
setMaxInactiveInterval(int interval) //设置session的存活时间 秒
invalidate() 使此会话无效
2、为什么要学HttpSession?
> 它也是一个域对象: session servletContext request
> 同一个会话下,可以使一个应用的多个资源共享数据
> cookie客户端技术,只能存字符串。HttpSession服务器端的技术,它可以存对象。
3、Session的内部执行原理
HttpSession request.getSession():内部执行原理
1、获取名称为JSESSIONID的cookie的值。
2、没有这样的cookie,创建一个新的HttpSession对象,分配一个唯一的SessionID,并且向客户端写了一个名字为JSESSIONID=sessionID的cookie
3、有这样的Cookie,获取cookie的值(即HttpSession对象的值),从服务器的内存中根据ID找那个HttpSession对象:
找到了:取出继续为你服务。
找不到:从2开始。
4、Session的状态
5、Demo1简单的购物车
Servlet1:首页
1 public void doGet(HttpServletRequest request, HttpServletResponse response) 2 throws ServletException, IOException { 3 response.setContentType("text/html; charset=UTF-8"); 4 PrintWriter out = response.getWriter(); 5 6 out.write("选择你要购买的<br/>"); 7 //遍历到所有的书 8 Map<String, Book> allBook = Utils.getAllBook(); 9 for (Entry<String, Book> book : allBook.entrySet()) { 10 out.write("<a href='" + request.getContextPath() 11 + "/servlet/addBook?id="+book.getKey()+"' target='_blank'>" 12 + book.getValue().getName() + "<a/><br/>"); 13 } 14 out.write("<a href='/day10_01_session/servlet/ShowCart' target='_blank'>查看cart</a>"); 15 }
Servlet2:购物车页面
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html; charset=UTF-8"); PrintWriter out = response.getWriter(); Map<Book,Integer> books = (Map<Book, Integer>) request.getSession().getAttribute("books"); //如果session为空说明没有买书 if(books == null) { out.write("你还没有购买书籍"); return; } //否则遍历这个集合,取出book对象遍历输出 for (Entry<Book,Integer> book : books.entrySet()) { out.write(book.getKey().getName()+"num: "+book.getValue().toString()); } }
Servlet3:买书页面(详情页面)
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String id = request.getParameter("id"); Book book = Utils.getMapById(id); HttpSession session = request.getSession(); //得到Session ,创建一个map集合,保存这个session, Map<Book, Integer> books = (Map<Book, Integer>) request.getSession().getAttribute("books"); //第一次为空所以如果是第一次那么就为null,表示这个书只有一本,那么新创建一个集合,放入这本书 if(books == null) { books = new HashMap<Book, Integer>(); books.put(book, 1); }else { //如果不是第一次且已经包含这本书了,那么就使这本书的value+1 if(books.containsKey(book)){ books.put(book, books.get(book)+1); }else { //否则,放入这1个这本书就行 books.put(book, 1); } } //将books这个map集合放入session session.setAttribute("books", books); }
没有设置Session的过期时间,可以自己设置,在上面的有两种设置方法.
6、用户禁用了Cookie的解决办法
解决方案:
方案一:在主页上给出提示:请不要禁用您的cookie
方案二:URL重写。必须对网站的所有地址都重写。
http://url--->http://url;JSESSIONID=111
response.encodeURL(String url);
看浏览器有没有发送cookie请求消息头,没有就重写URL,有就不重写。
request.getSession();必须写