天天看點

day11--cookie-session會話技術

  1. 會話技術概述

    在浏覽器和伺服器建立連結之後,浏覽器和伺服器為了完成某一功能,浏覽器發送一次或多次請求,伺服器作出的一次或多次響應,在浏覽器關閉之前,所有的請求和響應就構成了一次會話。

    1. HTTP協定特點:

      HTTP無狀态協定:目前請求和上一次請求之間沒有任何的聯系。

    2. 使用會話技術的原因:

      a. 為了能夠在多次請求響應之間共享資料,所有提出會話技術。

    3. 會話技術–cookie

      a. cookie的實作原理

      伺服器會在第一次響應的時候,通過set-cookie響應頭,将需要使用的資料發送到浏覽器,浏覽器會自動将其作為cookie儲存。在下一次請求時,會自動攜帶一個cookie請求頭,其中包含的内容就是浏覽器中的cookie資訊。

      b. cookie特點:

      cookie技術是一門浏覽器端的技術,資料儲存在浏覽器端。儲存安全性要求較低的資料。而存儲時間較長的資料。

      c. 案例:傳回上次通路頁面的時間:

      i. 在第一響應中,set-cookie儲存的資料會到達浏覽器。并且保留在浏覽器中。

      ii. 在下一次的請求中,使用cookie請求頭,擷取cookie,得到結果。

      代碼實作:

      package cn.tedu.cookie;

      import java.io.IOException;
       	import java.util.Date;
       	
       	import javax.servlet.ServletException;
       	import javax.servlet.http.HttpServlet;
       	import javax.servlet.http.HttpServletRequest;
       	import javax.servlet.http.HttpServletResponse;
       	//cookie原理實作
       	public class CookieDemo1 extends HttpServlet {
       	
       	        public void doGet(HttpServletRequest request, HttpServletResponse response)
       	                throws ServletException, IOException {
       	                //亂碼解決
       	                response.setContentType("text/html;charset=utf-8");
       	                //傳回頁面上一次的通路時間
       	                Date date = new Date();
       	                String time = date.toLocaleString();//擷取目前時間
       	                //1.設定set-cookie響應頭
       	                response.setHeader("set-cookie", "time="+time);
       	                //2.擷取請求頭cookie
       	                String cookie = request.getHeader("cookie");
       	                //3.列印結果
       	                if(cookie == null){//初次請求沒有cookie請求頭,是以cookie請求頭為null
       	                        
       	                        response.getWriter().write("您是初次通路本頁面");
       	                }else{
       	                        
       	                        response.getWriter().write("上次通路頁面的時間為:"+cookie);
       	                }
       	        }
       	
       	        public void doPost(HttpServletRequest request, HttpServletResponse response)
       	                throws ServletException, IOException {
       	                doGet(request, response);
       	
       	        }
       	
       	}
                 
    4. Cookie類

      Sun公司提供了一個Cookie類,可以通過建立對象的方式,來建立cookie。

      a. 建立cookie

      Cookie cookie = new Cookie(String name,String value);

      b. 設定cookie的生命時長

      cookie的生命時長可以設定也可以不設定。如果不設定則目前cookie的生命時長,則cookie為一個會話級别的cookie,關閉浏覽器目前cookie就會銷毀。如果設定生命時長,則達到對應時間之後,會有浏覽器自動銷毀。

      cookie.setMaxAge(秒);

      c. 設定有效路徑

      如果不設定有效路徑,則目前cookie的有效路徑為資源名稱部分,在這一部分中可以共享cookie。如果設定有效路徑,且為整個web應用,那麼在整個web應用的虛拟路徑級别之下都可以擷取到目前cookie

      cookie.setPath(request.getContextPath()+"/");

      d. 發送cookie

      response.addCookie(Cookie)

      e. 擷取cookie

      request.getCookies(); —Cookie[]

      f. 删除cookie

      發送一個與要删除的cookie完全相同的cookie,并且設定它的生命時長為0,則這個cookie就可以被銷毀。完全相同的cookie,需要保證name+path+domain三者完成一緻。

      g. 擷取cookie的名字

      cookie.getName()

      h. 擷取cookie的值

      cookie.getValue()

      i. 案例:通過cookie實作,頁面上次通路時間:

      package cn.tedu.cookie;

      import java.io.IOException;
       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;
       //Cookie類實作傳回上次通路頁面的時間
       public class CookieDemo2 extends HttpServlet {
       
               public void doGet(HttpServletRequest request, HttpServletResponse response)
                       throws ServletException, IOException {
                       //亂碼處理
                       response.setContentType("text/html;charset=utf-8");
                       Date date = new Date();
                       String time = date.toLocaleString();
                       //1.建立cookie
                       Cookie cookie = new Cookie("time",time);
                       //2.發送cookie--通過response對象發送
                       response.addCookie(cookie);
                       //3.擷取cookie
                       Cookie[] cs = request.getCookies();
                       //周遊數組
                       Cookie timeC = null;
                       if(cs !=null){//初次通路頁面時,沒有任何cookie,是以會産生空指針異常,應該排除這種情況
                               for(Cookie c:cs){
                                       if("time".equals(c.getName())){//從數組中擷取名稱為time的cookie
                                               timeC = c;//目前cookie對象範圍過小,無法在外側代碼操作,可以指派給更大範圍的變量去使用。
                                       }
                                       
                               }
                       }
                       
                       //4.列印結果
                       if(timeC == null){
                               response.getWriter().write("您是初次通路本頁面");
                               
                       }else{
                               response.getWriter().write("上次通路頁面的時間為:"+timeC.getValue());
                               
                       }
               }
       
               public void doPost(HttpServletRequest request, HttpServletResponse response)
                       throws ServletException, IOException {
                       doGet(request, response);
       
               }
       
       }
                 
    5. EasyMall功能實作—記住使用者名

      a. 導入login.jsp頁面

      i. 從課前資料中複制login頁面内容。

      ii. 将html頁面修改為jsp頁面

      b. 修改_head.jsp

      登入

      c. 建立LoginServlet.java

      package com.easymall.servlet;

      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;
       //登入Servlet
       public class LoginServlet extends HttpServlet {
       
               public void doGet(HttpServletRequest request, HttpServletResponse response)
                       throws ServletException, IOException {
                       //0.亂碼處理
                       request.setCharacterEncoding("utf-8");
                       response.setContentType("text/html;charset=utf-8");
                       //1.擷取參數
                       String username = request.getParameter("username");
                       String password = request.getParameter("password");
                       //擷取是否記住使用者名選項
                       String remname = request.getParameter("remname");//"true"   null
                       //2.記住使用者名--cookie
                       //remname為"true"則需要記住使用者名,反之為null不需要記住使用者名。
                       if("true".equals(remname)){
                               Cookie cookie = new Cookie("remname",URLEncoder.encode(username, "utf-8"));
                               cookie.setMaxAge(60*60*24*30);//30天記住使用者名
                               cookie.setPath(request.getContextPath()+"/");
                               response.addCookie(cookie);
                       }else{
                               Cookie cookie = new Cookie("remname", "");
                               cookie.setMaxAge(0);
                               cookie.setPath(request.getContextPath()+"/");
                               response.addCookie(cookie);
                       }
                       //3.儲存使用者登入狀态---session
                       //4.跳轉回首頁
       //		response.sendRedirect("http://www.easymall.com");
               response.sendRedirect(request.getContextPath()+"/");
               }
       
               public void doPost(HttpServletRequest request, HttpServletResponse response)
                       throws ServletException, IOException {
                       doGet(request, response);
       
               }
       
       }
                 

      d. 修改login.jsp:添加如下代碼

      <%

      //擷取cookie中的remname 讀取其中的使用者名

      Cookie[] cs = request.getCookies();

      Cookie remnameC = null;

      //初次擷取cookie數組為null

      if(cs !=null){

      for(Cookie c:cs){//周遊cookie數組,尋找remname這個cookie

      if(“remname”.equals(c.getName())){

      remnameC = c;

      }

      }

      }

      String username="";

      if(remnameC !=null){

      username = URLDecoder.decode(remnameC.getValue(), “utf-8”);

      }
               
               
                %>
               
       <td><input type="text" name="username" value="<%=username%>"/></td>
       <input type="checkbox" name="remname"  value="true"
               <%="".equals(username)?"":"checked='checked'" %>	
               
               />記住使用者名
                 
    6. session概述

      在浏覽器端儲存資料,資料可以被檢視、擷取,資料安全性較低。重要的資料應該存放在不容易擷取到的位置。伺服器是一個良好的選擇。資料通過伺服器共享,這門技術就是session會話技術。

    7. Session工作原理

      每一個浏覽器在通路伺服器時,都會建立各自對應的session對象來儲存資料。互相之間不會影響,是因為在session對象身上會包含一個sessionid,可以通過這個id來區分每一個浏覽器對應的session。

      a. session工作原理:

      本質是通過一個名稱為JSESSIONID的cookie來進行工作的。這個cookie會儲存在浏覽器中使用。

      b. session的特點:

      session是一門伺服器的技術,将資料儲存的伺服器端。儲存安全性要求較高的資料。且存儲時間較短的資料。

      c. 建立session對象

      request.getSession();//如果伺服器中有session對象,則取出使用,如果沒有session對象則建立一個新的session對象使用。

      request.getSession(true);//如果伺服器中有session對象,則取出使用,如果沒有session對象則建立一個新的session對象使用。

      request.getSession(false);//如果伺服器中沒有session對象,則傳回null,如果有session對想則取出使用。(判斷session是否存在時使用)

    8. 作為域對象使用

      域對象:如果一個對象身上有一個可以被看見的範圍,在這個範圍内利用對象身上的map實作資料的共享,這個對象就可以稱之為域對象。

      a. 操作api:

      setAttribute(String name,Object obj) 設定域屬性

      getAttribute(String name) 擷取域屬性

      removeAttribute(String name ) 删除域屬性

      getAttributeNames() 擷取所有的域屬性名稱

      b. 生命周期:

      request.getSession()方法調用的時候session對象産生。

      i. 意外身亡:在伺服器意外關閉的情況下,session對象會被銷毀。在伺服器正常關閉的情況下,如果session對象未被釋放,則其中的内容會序列化到磁盤上,這個過程,稱之為鈍化。當伺服器再次啟動的時候,會重新讀取磁盤上這個檔案,這個過程稱之為活化。

      ii. 自殺:主動session.invalidate()方法會立刻釋放目前session對象。

      iii. 逾時死亡:在[tomcat]/conf/web.xml中有session預設的最大生命時長配置标簽,預設值為30分鐘。超過30分鐘,則目前session會被釋放。

      c. 作用範圍:

      整個會話範圍。

      d. 主要功能:

      在整個會話範圍内共享資料

      e. 代碼實作:

      i. SessionDemo1.java

      package cn.tedu.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;
       	//session共享資料--作為域對象使用
       	public class SessionDemo1 extends HttpServlet {
       	
       	        public void doGet(HttpServletRequest request, HttpServletResponse response)
       	                throws ServletException, IOException {
       	                //1.擷取session對象
       	                HttpSession session = request.getSession();
       	                //2.作為域對象使用--設定域屬性
       	                session.setAttribute("name", "曹洋");
       	        }
       	
       	        public void doPost(HttpServletRequest request, HttpServletResponse response)
       	                throws ServletException, IOException {
       	                doGet(request, response);
       	
       	        }
       	
       	}
       ii. SessionDemo2.java
       	package cn.tedu.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 {
       	                //1.擷取session對象
       	                HttpSession session = request.getSession(true);
       	                //2.擷取域屬性
       	                String name = (String) session.getAttribute("name");
       	                System.out.println("name:"+name);
       	        }
       	
       	        public void doPost(HttpServletRequest request, HttpServletResponse response)
       	                throws ServletException, IOException {
       	                doGet(request, response);
       	
       	        }
       	
       	}
                 
    9. 案例:購物車

      兩個Servlet:buyServlet/PayServlet

      一個jsp:sale.jsp — 挑選商品 點選商品名稱加入購物車。點選付款按鈕為商品結賬。

      index.jsp頁面

      <%@ page language=“java” import=“java.util.*” pageEncoding=“utf-8” session=“false”%>

      </head>
       	  
       	  <body>
       	    <a href="http://localhost/day12-cookiesession/servlet/BuyServlet?prod=滑鼠" target="_blank" rel="external nofollow" >滑鼠</a><br>
       	    <a href="http://localhost/day12-cookiesession/servlet/BuyServlet?prod=鍵盤" target="_blank" rel="external nofollow" >鍵盤</a><br>
       	    <a href="http://localhost/day12-cookiesession/servlet/BuyServlet?prod=月餅" target="_blank" rel="external nofollow" >月餅</a><br>
       	    <a href="http://localhost/day12-cookiesession/servlet/BuyServlet?prod=手機" target="_blank" rel="external nofollow" >手機</a><br>
       	    <a href="http://localhost/day12-cookiesession/servlet/BuyServlet?prod=拖鞋" target="_blank" rel="external nofollow" >拖鞋</a><br>
       	    <a href="http://localhost/day12-cookiesession/servlet/PayServlet" target="_blank" rel="external nofollow" >付款</a><br>
       	  </body>
       	</html>
       buyServlet.java
       	package cn.tedu.session;
       	
       	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;
       	import javax.servlet.http.HttpSession;
       	//購物車Servlet
       	public class BuyServlet extends HttpServlet {
       	
       	        public void doGet(HttpServletRequest request, HttpServletResponse response)
       	                throws ServletException, IOException {
       	                //1.請求亂碼
       	                String prod = request.getParameter("prod");
       	                prod = new String(prod.getBytes("iso8859-1"),"utf-8");
       	                //2.響應亂碼處理
       	                response.setContentType("text/html;charset=utf-8");
       	                
       	                //将商品放入購物車
       	                //1.擷取session對象
       	                HttpSession session = request.getSession();
       	                //關閉浏覽器前後都要操作同一個session
       	                //---在浏覽器端保留一個名稱為JSESSIONID的cookie,cookie值存儲session的id
       	                Cookie cookie = new Cookie("JSESSIONID",session.getId());
       	                cookie.setMaxAge(60*60*24);
       	                cookie.setPath(request.getContextPath()+"/");
       	                response.addCookie(cookie);
       	                
       	                //2.向session中添加域屬性
       	                session.setAttribute("prod", prod);
       	                //3.在浏覽器中提示,商品加入購物車
       	                response.getWriter().write("商品【"+prod+"】已經加入購物車");
       	        }
       	
       	        public void doPost(HttpServletRequest request, HttpServletResponse response)
       	                throws ServletException, IOException {
       	                doGet(request, response);
       	
       	        }
       	
       	}
       PayServlet.java
       	package cn.tedu.session;
       	
       	import java.io.IOException;
       	
       	import javax.servlet.ServletException;
       	import javax.servlet.http.HttpServlet;
       	import javax.servlet.http.HttpServletRequest;
       	import javax.servlet.http.HttpServletResponse;
       	//支付Servlet
       	public class PayServlet extends HttpServlet {
       	
       	        public void doGet(HttpServletRequest request, HttpServletResponse response)
       	                throws ServletException, IOException {
       	                //從session中取出商品
       	                //1.響應亂碼處理
       	                response.setContentType("text/html;charset=utf-8");
       	                //2.判斷session是否存在--直接點選不會為任何商品付款
       	                if(request.getSession(false) != null){
       	                        //3.如果存在,則取出域屬性
       	                        String prod = (String) request.getSession().getAttribute("prod");
       	                        //釋放session,清空購物車。
       	                        request.getSession(false).invalidate();
       	                        //頁面提示已為商品付款
       	                        response.getWriter().write("您以為商品【"+prod+"】付款¥10000");
       	                }else{
       	                        //4.如果不存在則提示使用者尚未選擇商品
       	                        response.getWriter().write("您尚未選擇任何商品");
       	                }
       	        }
       	
       	        public void doPost(HttpServletRequest request, HttpServletResponse response)
       	                throws ServletException, IOException {
       	                doGet(request, response);
       	
       	        }
       	
       	}
                 
    10. EasyMall功能–登入

      通過登入功能,儲存使用者的登入狀态。

      request域~範圍太小

      ServletContext域~範圍太大

      session域–合适

      a. 修改LoginServlet.java,添加如下代碼:

      //3.儲存使用者登入狀态—session

      //判斷使用者名域密碼是否比對

      Connection conn = null;

      PreparedStatement ps = null;

      ResultSet rs = null;

      try {

      conn = JDBCUtils.getConnection();

      ps = conn.prepareStatement(“select * from user where username =? and password=?”);

      ps.setString(1, username);

      ps.setString(2, password);

      rs = ps.executeQuery();

      if(rs.next()){//使用者名和密碼正确,完成登入

      HttpSession session = request.getSession();

      session.setAttribute(“username”, username);

      }else{//傳回登入頁面作出提示

      request.setAttribute(“msg”, “使用者名或密碼不正确”);

      request.getRequestDispatcher("/login.jsp").forward(request, response);

      return;

      }

      } catch (SQLException e) {

      e.printStackTrace();

      }finally{

      JDBCUtils.close(conn, ps, rs);

      }

      //4.跳轉回首頁
       //		response.sendRedirect("http://www.easymall.com");
               response.sendRedirect(request.getContextPath()+"/");
                 

      b. _head.jsp頁面中添加如下内容:

      <%

      //判斷是否存在登入狀态

      if(request.getSession(false) != null

      && request.getSession().getAttribute(“username”)!=null){

      //第一個判斷是确認session對象是否存在,如果存在仍然不能确定是否包含username域屬性(登入狀态)

      //第二個判斷是确認目前session對象中是否包含username屬性,如果包含才從中取出使用者名,在頁面中顯示

      %>

      歡迎<%=request.getSession().getAttribute(“username”) %>,回來  |  

      登出

      <%

      }else{

      %>

      登入  |  

      注冊

      <%

      }

      %>

      c. 在login.jsp中添加錯誤提示框

      <%=request.getAttribute(“msg”)==null?"":request.getAttribute(“msg”) %>

    11. 登出功能

      修改_head.jsp頁面

      登出

      建立LogOutServlet.java

      package com.easymall.servlet;

      import java.io.IOException;

      import javax.servlet.ServletException;

      import javax.servlet.http.HttpServlet;

      import javax.servlet.http.HttpServletRequest;

      import javax.servlet.http.HttpServletResponse;

      //登出servlet

      public class LogOutServlet extends HttpServlet {

      public void doGet(HttpServletRequest request, HttpServletResponse response)
                   throws ServletException, IOException {
                   //登出使用者就是銷毀session
                   if(request.getSession(false) !=null){
                           
                           request.getSession().invalidate();
                   }
                   //跳轉回首頁
                   response.sendRedirect(request.getContextPath()+"/");
                   
           }
      
           public void doPost(HttpServletRequest request, HttpServletResponse response)
                   throws ServletException, IOException {
                   doGet(request, response);
      
           }
                 
      }
    12. 驗證碼實作

      a. 在ValidateServlet中添加如下内容:

      response.setDateHeader(“Expires”, -1);

      response.setHeader(“Cache-Control”, “no-cache”);

      VerifyCode vc = new VerifyCode();

      //目前servlet隻有img标簽調用,是以将圖檔放入緩沖區,

      //最終會在其調用的位置輸出在浏覽器中。

      vc.drawImage(response.getOutputStream());

      String code = vc.getCode();

      //添加驗證碼到session域

      request.getSession().setAttribute(“code”, code);

      System.out.println(code);

      System.out.println(“執行成功~!”);

      b. 在registServlet中添加如下内容:

      //6.驗證碼校驗

      //TODO:session

      //擷取域中驗證碼和使用者輸入的驗證碼,作比對

      String code = (String) request.getSession().getAttribute(“code”);

      if(!code.equalsIgnoreCase(valistr)){

      request.setAttribute(“msg”, “驗證碼錯誤”);

      request.getRequestDispatcher("/regist.jsp").forward(request, response);

      return;

      }

    13. Cookie特點:

      cookie是将資料儲存在浏覽器端,是一門浏覽器端的技術。由于資料儲存在浏覽器端,是以可以被任意的檢視,安全性較低,但是可以長時間存儲資料。cookie善于存儲安全性要求較低,但是存儲時間較長的資料。

    14. Session特點:

      session是将資料儲存在伺服器端,是一門伺服器端的技術,資料儲存在伺服器端相對安全,但是伺服器無法保留大量session對象,是以不能夠長時間存儲資料。伺服器善于存儲安全性要求較高,但是存儲時間較短的資料。