会话技术 Cookie和Session

一、获取ReqeustDispatcher的方式                                                                                   
       1、ServletContext   getRequestDispatcher(String path)
       2、ServletRequest getRequestDispatcher(String path)
       共同点:起到的作用是一样的
       不同点:在于方法的参数path的写法上
            1、path:必须是一个绝对路径。也就是说必须以“/”开头

            2、path:既可以是绝对路径,又可以是相对路径。不以"/"开头就是相对路径(路径必须正确)

二、转发和重定向的细节                                                                                                       
     1、转发:只能转发到本应用的其他资源
     2、请求重定向:可以转发到任何地址。

三、绝对路径的写法(都以/开头)                                                                                      

如果是给客户端用的,要加项目名称,否则(给服务器用的),不加项目名称

转发:request     getRequestDispatcher(String path)     不需要加项目名称 /servlet/Demo2
重定向:response   sendRedirect(String path)  需要加项目名称 /day06/servlet/Demo2
              Refresh=2;URL=path   需要加项目名称 /day06/servlet/Demo2
              form表单的action     需要加项目名称 /day06/servlet/Demo2
              a的href:      需要加项目名称 /day06/servlet/Demo2
              包含:include(String path)  不需要加项目名称 /servlet/Demo2 

四、什么是会话,如同打电话                                                                                                

会话过程中要解决的问题:用户数据的保存问题。保存在ServletContext和ServletRequest的域对象中是不可取的。

解决方案:

1、Cookie

是客户端技术,程序把每个用户的数据以cookie的形式写给用户各自的浏览器响应消息头Set-Cookie:key=value 请求消息头cookie:key=value
 一个cookie必须有name和value,还有以下可选属性
      comment: path:默认路径就是访问写写domain:
   名为abc的cookie的path:www.sina.com/mail
     http://localhost:8080/day06 能不能得到abc这个cookie。不能
     www.sina.com/mail 能不能得到abc这个cookie。能
     www.sina.com/mail/abc/a.jsp  能不能得到abc这个cookie。能

   如果把cookie的路径设置为:localhost/day06 说明day06下面的所有资源都可以访问这个cookie
   
 age:设置cookie的缓存时间。默认的时间是一个负数(浏览器关闭时删除)。如果是0,则是删除该cookie。正整数才是存活的时间。
 version:
 
 如何向客户端写一个cookie:
  HttpServletResponse.addCookie(javax.servlet.http.Cookie)
 注:每个服务器只能存放20 cookie (稀有)
 浏览器端最多能存放300cookie
 每个cookie的大小不能超过4Kb
 
 服务器如何获取客户端带来的cookie:
  HttpServletRequest.getCookies()
 注:不同网站向同一个客户端写的cookie的名称一致,可以通过cookie的path属性进行区分
 
 cookie的默认存活时间是会话范围。
 

2、HttpSession
 是服务器端技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的session对象
 如何得到HttpSession对象:
  HttpServletRequest  getSession()
 其实session技术利用了cookie技术:
  向客户端写了一个名字为JSESSIONID的cookie
  value:session对象的id
  path:/day06 request.getContextPath()
  age:负数
特别注意:
 关闭浏览器是结束一次会话。但是对于服务器来讲,并不会立刻销毁内存中的session对象。默认的session的存活时间是30分钟。
 getSession():如果内存中有对应的session,它是获取方法。如果没有,则创建新的session。
 getSession(true)功能同没有参数的
 getSession(false):如果内存中有对应的session,它是获取方法。如果没有,返回null 
--------------------------------------------------------------------------------------------------------------------------

Cookie案例:
eg1:记录用户最近一次的访问时间
  每次访问页面的时候将系统时间记录下来

 Cookie c = new Cookie("lastAccessTime",System.currentTimeMillis()+"");
        //设置Cookie有限期
        c.setMaxAge(Integer.MAX_VALUE);
        c.setPath(request.getContextPath());
        //写回Cookie
        response.addCookie(c);
  
      //清除上一次访问的时间
      //得到所有的Cookies  //day06/servlet路径下
       Cookie cookies[]= request.getCookies(); 
      //进行遍历查找对应的 Cookie ,并对其进行设置
      for(int i =0 ;cookies!=null&&i

eg2:记住用户名
  常量接口设计模式
  a)使用场景:在程序设计中,我们可以把所用要用到的常量设计为一个独立的类,使得对常量的管理有效清晰。

public interface MyConstant {
     //接口常量,这样可以避免拼写错误
        String USERNAME = "username";
        }
  CookieDemo1中:
  //让用户名默认为空,记录用户名被checked时才根据Cookie显示
  String username = "";
  String checked = "";
  //根据Cookie决定是否显示用户名
  Cookie cookies[] = request.getCookies();
  for(int i = 0;cookies!=null&&i用户登录");
    out.print("
"); out.print("用户名:
"); out.print("密码:
"); out.print("
"); out.print("记住用户名"); out.print("
");
CookieDemo2中;
  // 获取表单中的信息,进行验证
  String username = request.getParameter("username");
  String remeber = request.getParameter("remeber");
  if (remeber == null) {// 不需要记住 ,需要清空Cookie
   Cookie cookies[] = request.getCookies();
            for(int i =0;cookies!=null&&i
eg3:购物网站中的应用,记住用户最近浏览的商品记录
   ShowAllBookServlet;
   //列出所有的书籍
  response.setContentType("text/html;charset=UTF-8");
  PrintWriter out = response.getWriter();
  Map books = BookDb.getBooks();
  for(Map.Entry me:books.entrySet()){
   out.print(""+me.getValue().getName()+"
"); } //显示最近浏览的商品列表,最多三件 out.print("
"); out.print("最近浏览过的商品:
"); //根据Cookie中保存的信息进行显示 Cookie cookies[] = request.getCookies(); for(int i=0;cookies!=null&&i"); } break; } }

ShowDetailsServlet:
       doGet():

    PrintWriter  out = response.getWriter();
       out.print("书的详细信息如下
");; String id = request.getParameter("id"); Book book = BookDb.findBookById(id); out.print("名称:"+book.getName()+"
"); out.print("作者:"+book.getAuthor()+"
"); out.print("价格:"+book.getPrice()+"
"); out.print("评价:"+book.getDescription()+"
"); //将书的id保存到Cookie中 String value = makeId(id,request); Cookie cookie = new Cookie(MyConstant.BOOK_HISTORY, value); //设置Cookie属性 cookie.setMaxAge(Integer.MAX_VALUE); cookie.setPath(request.getContextPath()); //写回Cookie response.addCookie(cookie); /* **进行字符串拼接,根据用户当前浏览的书id 拼出浏览信息,如 1-2-3 */ private String makeId(String id, HttpServletRequest request) { Cookie cookies[] = request.getCookies(); //cookies为空,为第一次访问书籍 if(cookies==null) return id; Cookie cookie = null;//记录book_history for(Cookie c : cookies){ //若存在name为BOOK_HISTORY的Cookie ,用cookie记录 if(MyConstant.BOOK_HISTORY.equals(c.getName())){ cookie = c; break; } } if(cookie==null)//有cookie但没有name为book_history的cookie return id; String value = cookie.getValue(); String ids[] = value.split("\\-"); LinkedList list = new LinkedList(Arrays.asList(ids)); if(list.size()<3){//浏览商品少于三件 if(list.contains(id)){ //浏览过,从原来记录中删除,然后将其添加到第一位 list.remove(id); list.addFirst(id); }else{ //没有浏览过,直接添加到第一位 list.addFirst(id); } }else{//浏览商品正好三件 if(list.contains(id)){ //浏览过,从原来记录中删除,然后将其添加到第一位 list.remove(id); list.addFirst(id); }else{ //没有浏览过,先移除最末一位.然后将当前浏览商品添加到第一位 list.removeLast(); list.addFirst(id); } } StringBuffer sb = new StringBuffer(); for(int i=0;i0){//从第一个id后添加- sb.append("-"); } sb.append(list.get(i)); } return sb.toString(); }

Session 案例

eg1:简单的购物车

ShowAllProductsServlet 显示所有的商品,提供购买的超链接

//列出所有的书籍
  response.setContentType("text/html;charset=UTF-8");
  PrintWriter out = response.getWriter();
  out.print("本站有以下书籍
"); Map books = BookDb.getBooks(); for(Map.Entry me:books.entrySet()){ out.print(me.getValue().getName()+"购买
"); } BuyServlet 将当前购买的商品添加到购物车中 String id = request.getParameter("id"); Book book = BookDb.findBookById(id); HttpSession session = request.getSession(); List carts = (List) session.getAttribute("carts"); if(carts==null){ carts = new ArrayList(); carts.add(book); session.setAttribute("carts", carts); }else{//若已经存在session则直接添加 carts.add(book); } response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); out.print("继续购物
去结算");
ShowCartServlet 显示购物车中的商品
 response.setContentType("text/html;charset=UTF-8");
      PrintWriter out =response.getWriter();
      HttpSession session = request.getSession();
      List carts = (List) session.getAttribute("carts");
      out.print("购物车中的商品:");
      for(Book book:carts){
       out.print(book.getName()+"
"); } out.print("去付款");

BookDb 模拟数据库信息
public class BookDb {
 // key->id value->book
 public static Map books = new HashMap();
    /*
     * 初始化时添加五本书
     */
 static{
     books.put("1", new Book("1","JAVA疯狂讲义","李刚","58.00","非常好的入门书"));
     books.put("2", new Book("2","java入门详解","张孝祥","99.00","好得不行了"));
     books.put("3", new Book("3","javascript","毕向东","55.00","经典初级入门"));
     books.put("4", new Book("4","web深入开发","方立勋","89.00","不错哦"));
     books.put("5", new Book("5","安卓深入浅出","老田","110.00","深入浅出经典之作"));
    }
 public static Map getBooks() {
  return books;
 }
    //通过id找到对应的书
 public static Book findBookById(String id){
  return books.get(id);
 }
}
eg2:简单的用户登录
 LoginServlet:

 request.setCharacterEncoding("UTF-8");
       response.setContentType("text/html;charset=UTF-8");
      
       String username = request.getParameter("username");
       String password = request.getParameter("password");
      
       PrintWriter out = response.getWriter();
       User user = new User();
       user.setUsername(username);
       user.setPassword(password);
      
       HttpSession session = request.getSession();
       session.setAttribute("user", user);
       out.print("登录成功,两秒后进行跳转");
       //登录成功,两秒后进行跳转
       response.setHeader("Refresh", "2;url=/day06/servlet/IndexServlet");
IndexServlet
     response.setContentType("text/html;charset=UTF-8");
     PrintWriter out = response.getWriter();
    
     HttpSession session = request.getSession();
     User user = (User) session.getAttribute("user");
    
     out.print("欢迎"+user.getUsername()+"登录
"); out.print("这里是主页");

eg3:登录时进行验证码校验

ImageServlet生成验证码时中记录下来,先进行加密,然后放到session中

 StringBuffer sb = new StringBuffer();
  
  for(int i = 0;i<4;i++){
   int num = r.nextInt(10);
   g.drawString(num+"", x, 15);
   x+=20;
   sb.append(num);
  }
   //得到生成的验证码
  String code = sb.toString();
  
  //用md5算法对验证码进行加密
  code = Md5Util.encode(code);
  
  HttpSession session = request.getSession();
  session.setAttribute("code", code);    
 在LoginServlet中将页面用户输入的验证码和生成的验证码进行对比
  String code = request.getParameter("code");
        PrintWriter out = response.getWriter();
     
        HttpSession session = request.getSession();
        //code2是正确的验证码,与用户填入的进行对比
        String code2 = (String) session.getAttribute("code");
        if(!code2.equals(Md5Util.encode(code))){
         out.print("对不起,验证码输入失败");
      //跳转回登录页面
         response.setHeader("Refresh", "2;url=/day06/Login2.html");
         return;
        }

加密类Md5Util

 public class Md5Util {

 public static String encode(String code) {
  try{
     //得到md5算法的数据摘要
  MessageDigest md = MessageDigest.getInstance("md5");
  //根据MD5算法得到的数据指纹
  byte[] b = md.digest(code.getBytes());
  //用base64编码,将没有对应字符的二进制转为可见的字符
  BASE64Encoder base64 = new BASE64Encoder();
  
  return base64.encode(b);
  
  }catch(Exception e){
   throw new RuntimeException(e);
  }
 
 }
  
}
eg4:防止表单的重复提交
javascript在点击提交按钮后,将其设置为disabled

function toSubmit(btnObj){
     var formObj = document.getElementById("f1");
     btnObj.disabled=true;
     formObj.submit();
    }
但用户刷新后仍可以重复提交,不能根本解决问题
 
   解决方案:
   生成一个UUid (随即且唯一) ,保存在session中,然后同页面中hidden的输入框中的id进行比较
  public class UUidUtil {
 public static String getId() {
  return UUID.randomUUID().toString();
 } 
}
ServletDemo0:
 //生成登录页面
       response.setContentType("text/html;charset=UTF-8");
       PrintWriter out = response.getWriter();
       //随机生成一个唯一的码
       String id = UUidUtil.getId();
       out.print("
"+ "姓名:
"+ ""+ ""); HttpSession session = request.getSession(); session.setAttribute("id", id); ServletDemo1: request.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); String username = request.getParameter("username"); String ctoken = request.getParameter("token"); HttpSession session =request.getSession(); String stoken = (String) session.getAttribute("id"); PrintWriter out = response.getWriter(); if(ctoken.equals(stoken)){//不一致 进行提交,然后移除session 里的id,让用户可以进行新的提交 System.out.println(username); session.removeAttribute("id"); }else{//一致,说明是重复提交 out.print("表单不能重复提交"); return; }

原文链接::http://blog.csdn.net/t12x3456/article/details/7583582






你可能感兴趣的:(其他)