Cookie和Session
什么是会话?
会话可以简单理解为:用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话。
保存会话数据的两种技术:Cookie和HttpSession
Cookie:
Cookie是客户端技术,程序把每个用户的数据以cookie的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的web资源时,就会带着各自的数据去。这样,web资源处理的就是用户各自的数据了。
1.Cookie入门案例(上次访问时间)
package cn.lsl.cookie; import java.io.IOException; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; 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 LastVisit extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setDateHeader("Expires", -1); response.setHeader("Cache-Control", "no-cache"); response.setHeader("Pragma", "no-cache"); response.setContentType("text/html;charset=utf-8"); // 如果用户第一次访问 --- 判断请求中有没有cookie信息 Cookie[] cookies = request.getCookies(); if (cookies == null) { // 第一次访问,没有cookie,将当前时间以cookie写回客户端 long now = System.currentTimeMillis(); // 向客户端写cookie Cookie cookie = new Cookie("last", now + ""); cookie.setPath("/Cookie"); // 设置cookie有效时间 cookie.setMaxAge(60 * 60 * 24 * 2); // 写cookie回到客户端 response.addCookie(cookie); response.getWriter().println("欢迎你第一次访问本网站!"); } else { // cookie存在 for (Cookie cookie : cookies) { if (cookie.getName().equals("last")) { long lasttime = Long.parseLong(cookie.getValue()); // 显示给用户 Date date = new Date(lasttime); DateFormat dateFormat = new SimpleDateFormat( "yyyy年MM月dd日 HH时mm分ss秒"); response.getWriter().println( "上次访问时间:" + dateFormat.format(date)); } } // 更新最后访问时间 long now = System.currentTimeMillis(); Cookie cookie = new Cookie("last", now + ""); cookie.setPath("/Cookie"); cookie.setMaxAge(60 * 60 * 24 * 2); response.addCookie(cookie); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
解析:
1)通过服务器向客户端cookie
Cookie cookie = new Cookie(name,value);
response.addCookie(cookie);
* 在HTTP协议响应头信息中 Set-Cookie: last=1339556457609
2)当客户端存在cookie之后,以后每次请求自动携带HTTP协议请求头信息
Cookie: last=1339556456859
服务端获得需要cookie数据
Cookie[] cookie = request.getCookie();
遍历cookie获取需要信息
for(Cookie cookie : cookie){
if(cookie.getName().equals("last")){
}
}
2.会话cookie,持久cookie?
1)cookie信息默认情况保存在浏览器内存中 --- 会话cookie
会话cookie会在关闭浏览器时清除
2)持久cookie,cookie数据保存客户端硬盘上
通过setMaxAge设置Cookie为持久Cookie
3.访问cookie有效路径
默认情况下,生成cookie时,产生默认有效访问路径 (默认生成cookie程序路径)
http://localhost:8080/Cookie/lastvisit --- 生成cookie --- path 默认值: /Cookie
http://localhost:8080/Cookie/servlet/path ---- 生成cookie ---- path 默认值:/Cookie/servlet
第二次访问程序携带cookie信息,如果访问路径与path不一致,不会携带cookie 信息
* 以后程序开发,尽量设置path ---- setPath方法
4.第一方cookie 和 第三方cookie
通过setDomain 设置cookie 有效域名
访问google时,生成cookie过程中 cookie.setDomain(".baidu.com") ---- 生成百度cookie ------ 第三方cookie
* 第三方cookie 属于不安全 ----- 一般浏览器不接受第三方cookie
访问google时,生成cookie,cookie.setDomain(.google.con) ---- 生成google的cookie ------ 第一方cookie
5.删除cookie
原理:设置cookie MaxAge为0
*删除cookie时,必须设置path与cookie的path一致
eg:
package cn.lsl.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 DeleteCookie extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Cookie cookie = new Cookie("last",""); cookie.setMaxAge(0); cookie.setPath("/Cookie"); response.addCookie(cookie); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response); } }
6.显示上次浏览的商品
Book.java(实体类)
package cn.lsl.domain; public class Book { private String id; private String name; private String author; private Double price; private String description; public Book(){} public Book(String id, String name, String author, Double price, String description) { super(); this.id = id; this.name = name; this.author = author; this.price = price; 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 Double getPrice() { return price; } public void setPrice(Double price) { this.price = price; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } @Override public String toString() { return "Book [author=" + author + ", description=" + description + ", id=" + id + ", name=" + name + ", price=" + price + "]"; } }
BookDB.java(模拟数据库)
package cn.lsl.db; import java.util.LinkedHashMap; import java.util.Map; import cn.lsl.domain.Book; public class BookDB { private static Map<String, Book> books = new LinkedHashMap<String, Book>(); static{ books.put("1", new Book("1", "Java", "张三", 35.00, "Java入门")); books.put("2", new Book("2", "JavaEE", "李四", 45.00, "JavaEE入门")); books.put("3", new Book("3", "Android", "王五", 45.00, "Android入门")); books.put("4", new Book("4", "ios", "小舒", 55.00, "ios入门")); books.put("5", new Book("5", "html5", "小五", 35.00, "html5入门")); } //根据id查询书本 public static Book findBookById(String bookId){ return books.get(bookId); } //查询所有的书本 public static Map<String, Book> findAllBooks(){ return books; } }
ShowBookServlet.java(显示所有书籍)
package cn.lsl.cookie; import java.io.IOException; import java.io.PrintWriter; import java.util.Map; 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 cn.lsl.db.BookDB; import cn.lsl.domain.Book; public class ShowBookServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); out.write("<h1>本站有以下书籍</h1>"); Map<String, Book> books = BookDB.findAllBooks(); for (Map.Entry<String, Book> me : books.entrySet()) { out.write(me.getValue().getName()+" <a href='/Cookie/servlet/ShowBookDetailServlet?id="+me.getKey()+"'>查看详情</a><br/>"); } //显示用户最近的浏览记录 out.write("<hr/>"); out.write("<a href='/Cookie/servlet/CleanHistoryServlet'>清空浏览记录</a>"); out.write("<h3>您最近的商品浏览记录</h3>"); Cookie[] cs = request.getCookies(); for(int i=0; cs!=null&&i<cs.length; i++){ if("bookHistory".equals(cs[i].getName())){ String value = cs[i].getValue(); String ids[] = value.split("\\-"); for (String id : ids) { out.write(BookDB.findBookById(id).getName()+"<br/>"); } break; } } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response); } }
ShowBookDetailServlet.java(查看详细信息)
package cn.lsl.cookie; import java.io.IOException; import java.io.PrintWriter; import java.util.Arrays; 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 cn.lsl.db.BookDB; import cn.lsl.domain.Book; public class ShowBookDetailServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); String id = request.getParameter("id"); Book book = BookDB.findBookById(id); out.write(book.toString()); //向客户端写Cookie String ids = makeIds(request, id); Cookie c = new Cookie("bookHistory",ids); c.setMaxAge(Integer.MAX_VALUE); c.setPath(request.getContextPath()); response.addCookie(c); } private String makeIds(HttpServletRequest request, String id) { // TODO Auto-generated method stub //a Cookie cs[] = request.getCookies(); if(cs == null) return id; //b Cookie cookie = null; for (Cookie c : cs) { if("bookHistory".equals(c.getName())){ cookie = c; break; } } if(cookie == null) return id; //cdefg String ids[] = cookie.getValue().split("\\-"); LinkedList<String> list = new LinkedList<String>(Arrays.asList(ids)); if(list.size()<3){ if(list.contains(id)){ list.remove(id); } list.addFirst(id); }else{ if(list.contains(id)){ list.remove(id); }else{ list.removeLast(); } list.addFirst(id); } StringBuffer sb = new StringBuffer(); for (int i = 0; i < list.size(); i++) { if(i>0) sb.append("-"); sb.append(list.get(i)); } return sb.toString(); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response); } }
CleanHistoryServlet.java
package cn.lsl.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 CleanHistoryServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Cookie cookie = new Cookie("bookHistory",""); cookie.setMaxAge(0); cookie.setPath(request.getContextPath()); response.addCookie(cookie); response.sendRedirect("/Cookie/servlet/ShowBookServlet"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response); } }
7.Cookie细节
1)一个Cookie只能标识一种信息,它至少含有一个标识该信息的名称和设置值。
2)一个WEB站点可以给一个WEB浏览器发送多个Cookie,一个WEB浏览器可以存储多个WEB站点提供的Cookie。
3)浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,,每个Cookie的大小限制为4KB.
4)如果创建了一个Cookie,并将他发送到浏览器,默认情况下它是一个会话级别的cookie(即存储在浏览器的内存中),用户推出浏览器之后即被删除。若希望浏览器将还cookie存储在磁盘上,则需要使用maxAge,并给出一个以秒为单位的时间。将最大时效设为0则是命令浏览器删除该cookie。
4)删除cookie时,path必须一致,否则不会删除。
HttpSession
Session是服务器端技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的HttpSession对象,由于session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的数据放在各自的session中,当用户再去访问服务器中的其他web资源时,其他web资源再从个各自用户的session中取出数据为用户服务。
Session和Cookie的主要区别:
1)Cookie是把用户的数据写给用户浏览器的。Session技术把用户的数据写到用户独占的session中,
2)Session对象由服务器创建,开发人员可以调用request对象的getSession方法得到session对象。
Session快速入门案例(实现数据共享)
SessionDemo1.java
package cn.lsl.session; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class SessionDemo1 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String name = request.getParameter("name"); HttpSession session = request.getSession(); System.out.println(session.getId()); session.setAttribute("username", name); PrintWriter out = response.getWriter(); out.write("put done!"); out.write("<a href='/Session/servlet/SessionDemo2'>link</a>"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response); } }
SessionDemo2.java
package cn.lsl.session; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class SessionDemo2 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(); String value = (String)session.getAttribute("username"); response.getWriter().write(value); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response); } }
注:
HttpServletRequest.getSession():根据特殊Cookie(JSESSIONID=HttpSession对象的id,由服务器生成,唯一的)的取值,在服务器的内存中根据id查找这个HttpSession对象,找到了,取出来继续服务;没有找到,创建一个新的HttpSession对象。
HttpServletRequest.getSession(boolean b):如果b为true,与上面方法功能完全一致。如果为false,只查询。
案例:用户的一次性登陆和随机验证码验证
User.java(实体类)
package cn.lsl.domain; public class User { private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
ImageServlet.java(随机验证码)
package cn.lsl.code; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Random; import javax.imageio.ImageIO; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ImageServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 通知浏览器不要缓存 response.setHeader("Expires", "-1"); response.setHeader("Cache-Control", "no-cache"); response.setHeader("Pragma", "no-cache"); int width = 120; int height = 25; // 创建一副内存图像BufferedImage BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 得到属于该图片的画笔:Graphics(); Graphics g = image.getGraphics(); // 画边框 g.setColor(Color.BLUE); g.drawRect(0, 0, width, height); // 填充背景色 g.setColor(Color.YELLOW); g.fillRect(1, 1, width - 2, height - 2); // 画干扰线 g.setColor(Color.GRAY); Random r = new Random(); for (int i = 0; i < 10; i++) g.drawLine(r.nextInt(width), r.nextInt(height), r.nextInt(width), r .nextInt(height)); // 随机数字 g.setColor(Color.RED); g.setFont(new Font("宋体", Font.BOLD | Font.ITALIC, 20)); int x = 23; StringBuffer sb = new StringBuffer(); for (int i = 0; i < 4; i++) { String code = r.nextInt(10) + ""; sb.append(code); g.drawString(code , x, 20); x = x + 20; } //把验证码放到HttpSession中 request.getSession().setAttribute("code", sb.toString()); // 输出到浏览器的页面上:ImageIO ImageIO.write(image, "jpg", response.getOutputStream()); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
login.html(登陆页)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>login.html</title> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="this is my page"> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> </head> <body> <form action="/Session/servlet/LoginServlet" method="post"> 用户名:<input type="text" name="username" /><br/> 密码:<input type="password" name="password" /><br/> 验证码:<input type="text" name="code" /><img src="/Session/servlet/ImageServlet"><br/> <input type="submit" value="登陆" /> </form> </body> </html>
IndexServlet.java(主页)
package cn.lsl.code; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import cn.lsl.domain.User; public class IndexServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); HttpSession session = request.getSession(); User user = (User)session.getAttribute("user"); if(user == null){ out.write("<a href='/Session/login.html'>登陆</a>"); }else{ out.write("欢迎您:"+user.getUsername()+" <a href='/Session/servlet/LogoutServlet'>注销</a>"); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response); } }
LoginServlet.java(登陆)
package cn.lsl.code; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import cn.lsl.domain.User; public class LoginServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); //验证用户名和密码是否正确 String username = request.getParameter("username"); String password = request.getParameter("password"); String code = request.getParameter("code"); String sessionCode = (String)request.getSession().getAttribute("code"); if(!code.equalsIgnoreCase(sessionCode)){ out.write("错误的验证码<a href='/Session/login.html'>返回</a>"); return; } StringBuffer sb = new StringBuffer(password); password = sb.reverse().toString(); if(username.equals(password)){ User user = new User(); user.setUsername(username); user.setPassword(password); request.getSession().setAttribute("user", user); out.write("登陆成功。2秒后自动转回主页"); }else{ out.write("错误的用户名或密码。2秒后自动转回主页"); } response.setHeader("Refresh", "2;URL=/Session/servlet/IndexServlet"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response); } }
LogoutServlet.java(注销)
package cn.lsl.code; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class LogoutServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); request.getSession().removeAttribute("user"); out.write("注销成功!2秒后将自动跳转向主页"); response.setHeader("Refresh", "2;URL=/Session/servlet/IndexServlet"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response); } }
简单的购物车案例
Book.java(实体类)
package cn.lsl.domain; import java.io.Serializable; public class Book implements Serializable { private String id; private String name; private String author; private Double price; private String description; public Book(){} public Book(String id, String name, String author, Double price, String description) { super(); this.id = id; this.name = name; this.author = author; this.price = price; 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 Double getPrice() { return price; } public void setPrice(Double price) { this.price = price; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } @Override public String toString() { return "Book [author=" + author + ", description=" + description + ", id=" + id + ", name=" + name + ", price=" + price + "]"; } }
BookDB.java(模拟数据库)
package cn.lsl.db; import java.util.LinkedHashMap; import java.util.Map; import cn.lsl.domain.Book; public class BookDB { private static Map<String, Book> books = new LinkedHashMap<String, Book>(); static{ books.put("1", new Book("1", "Java", "张三", 35.00, "Java入门")); books.put("2", new Book("2", "JavaEE", "李四", 45.00, "JavaEE入门")); books.put("3", new Book("3", "Android", "王五", 45.00, "Android入门")); books.put("4", new Book("4", "ios", "小舒", 55.00, "ios入门")); books.put("5", new Book("5", "html5", "小五", 35.00, "html5入门")); } //根据id查询书本 public static Book findBookById(String bookId){ return books.get(bookId); } //查询所有的书本 public static Map<String, Book> findAllBooks(){ return books; } }
ShowAllBooksServlet.java(显示所有书籍)
package cn.lsl.cart; import java.io.IOException; import java.io.PrintWriter; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import cn.lsl.db.BookDB; import cn.lsl.domain.Book; public class ShowAllBooksServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); request.getSession(); //显示所有商品 out.write("<h1>本站有以下商品</h1>"); Map<String,Book> books = BookDB.findAllBooks(); for (Map.Entry<String, Book> me : books.entrySet()) { String url = "/Session/servlet/BuyServlet?id="+me.getKey(); url = response.encodeURL(url); out.write(me.getValue().getName()+" <a href='"+url+"'>购买</a><br/>"); } //提供出查看购物车的链接 String url = "/Session/servlet/ShowCartServlet"; url = response.encodeURL(url); out.write("<a href='"+url+"'>查看购物车</a>"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response); } }
BuyServlet.java(加入购物车)
package cn.lsl.cart; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; 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 javax.servlet.http.HttpSession; import cn.lsl.db.BookDB; import cn.lsl.domain.Book; public class BuyServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); String id = request.getParameter("id"); Book book = BookDB.findBookById(id); //先查看有无购物车,如果有,直接用,没有就创建一个 HttpSession session = request.getSession(); List<Book> cart = (List<Book>) session.getAttribute("cart"); if(cart == null){ cart = new ArrayList<Book>(); session.setAttribute("cart", cart); } cart.add(book); out.write(book.getName()+"已经放入购物车<br/>"); String url = "/Session/servlet/ShowAllBooksServlet"; url = response.encodeURL(url); out.write("<a href='"+url+"'>继续购物</a>"); //自己写Cookie Cookie c = new Cookie("JSESSIONID",session.getId()); c.setPath(request.getContextPath()); c.setMaxAge(Integer.MAX_VALUE); response.addCookie(c); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response); } }
ShowCartServlet.java(查看购物车)
package cn.lsl.cart; import java.io.IOException; import java.io.PrintWriter; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import cn.lsl.domain.Book; public class ShowCartServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); HttpSession session = request.getSession(false); if(session == null){ out.write("对不起!您还未曾购物"); }else{ List<Book> cart = (List<Book>) session.getAttribute("cart"); if(cart == null){ out.write("对不起!您还未曾购物"); }else{ out.write("您购买的商品如下:<br/>"); for (Book book : cart) { out.write(book.getName()+"<br/>"); } } } String url = "/Session/servlet/ShowAllBooksServlet"; url = response.encodeURL(url); out.write("<a href='"+url+"'>继续购物</a>"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response); } }
拓展:重写url
url---->url;JSESSIONID=123:URL重写.必须对网站中的所有URL地址都重写。
HttpServletResponse.encodeURL(url):是一个智能方法。判断用户是否禁用了Cookie,没有禁用,则不重写;禁用了就重写。
案例:防止表单重复提交
原理:表单页面由servlet程序生成,servlet为每次产生的表单页面分配一个唯一的随机标识号,并在FROM表单的一个隐藏字段中设置这个标识号,同时在当前用的session域中保存这个标识号。当用户提交FROM表单时,负责处理表单提交的servlet得到表单的标识号,并与session中存储的标识号比较,如果相同则处理表单提交,处理完后清除当前用户的Session域存储的标识号。
在下列情况下,服务器程序将拒绝用户提交的表单请求:
1)存储Session域中的表单标识号与表单提交的标识号不同
2)当前用户的Session中不存在表单标识号
3)用户提交的表单数据中没有标识号字段
原理图:
RegistUIServlet.java
package cn.lsl.session; import java.io.IOException; import java.io.PrintWriter; import java.util.UUID; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class RegistUIServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); //随机生成一个令牌 String token = UUID.randomUUID().toString();//唯一的一段序列 //放入HttpSession中 request.getSession().setAttribute("token", token); out.write("<form id='f1' action='"+request.getContextPath()+"/servlet/RegistServlet' method='post'>"); out.write("姓名:<input type='text' name='name'/><br/>"); out.write("<input type='hidden' name='token' value='"+token+"'/>"); out.write("<input id='bt1' type='button' value='注册' onclick='toSubmit()'/></form>"); out.write("<script type='text/javascript'>function toSubmit(){document.getElementById('f1').submit();document.getElementById('bt1').disabled=true;}</script>"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response); } }
RegistServlet.java
package cn.lsl.session; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class RegistServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); request.setCharacterEncoding("UTF-8"); String name = request.getParameter("name"); //判断用户是否重复提交 String formToken = request.getParameter("token"); String sessionToken = (String)request.getSession().getAttribute("token"); if(formToken.equals(sessionToken)){ //正常提交 System.out.println("保存了:"+name); request.getSession().removeAttribute("token"); }else{ out.write("请不要重复提交"); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response); } }
更改内存中HttpSession对象的超时时间
修改web.xml
<session-config> <session-timeout>1</session-timeout><!--自然整数,单位是分钟--> </session-config>