1. 程式人生 > >Day12--Servlet中的Cookie+Session

Day12--Servlet中的Cookie+Session

Servlet接收不同的表單資料

<form action="/s1" method="post">
    <!-- name 是引數名 -->
    <input type="date" name="birthday" value="2018-09-15">
    <hr>
    男
    <!-- MALE  FEMALE -->
    <input type="radio" name="sex" value="男" checked>
    女
    <input type="radio" name="sex" value="女">

    <hr>
    唱歌<input type="checkbox" name="hobby" value="1">
    跳舞<input type="checkbox" name="hobby" value="2">
    睡覺<input type="checkbox" name="hobby" value="3">
    玩遊戲<input type="checkbox" name="hobby" value="4">

    <hr>
    <!-- option 標籤如果不提供 value屬性, 把標籤之間的文本當成value
         如果提供了value屬性,以value為準
    -->
    <select name="city">
        <option>北京</option>
        <option>天津</option>
        <option value="shanghai">上海</option>
        <option>武漢</option>
    </select>

    <hr>
    個人簡介:
    <textarea name="intro" cols="30" rows="10"></textarea>
    <input type="submit" value="提交">
</form>


@WebServlet(urlPatterns = "/s1")
public class Servlet1 extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 處理漢字亂碼
        req.setCharacterEncoding("utf-8");

        // 1) 日期型別的接收,需要注意轉換字串為java中的Date型別
        String birthday = req.getParameter("birthday");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date date = sdf.parse(birthday);
            System.out.println(date);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        
        // 2) 處理單選按鈕
        String sex = req.getParameter("sex");
        System.out.println(sex);

        // 3) 處理複選框, 注意處理null值(都沒有勾選時,就是null值)
        String[] hobbies = req.getParameterValues("hobby");
        if(hobbies != null) {
            for (String hobby : hobbies) {
                System.out.println(hobby);
            }
        }

        // 4)處理下拉列表
        String city = req.getParameter("city");
        System.out.println(city);

        // 5)處理文字域
        String intro = req.getParameter("intro");
        System.out.println(intro);
    }
}

JSP的九大內建物件:  無需宣告即可使用的物件

     request:            代表請求物件(可以獲取請求引數,將變數儲存到 request作用域 中)

                              request的作用域只在一次請求內有效

     response:         代表響應物件(返回響應)

     out:                   代表響應的字元輸出流

     pageContext:    代表頁面上下文物件,可以間接獲得request等物件,並可以將變數存入page作用域

     session:            代表會話物件

,變數的作用範圍是 一次會話 內有效

     application:       代表一個應用程式物件,變數的範圍是 整個應用程式 內有效

     page:                當前 jsp頁面(相當於 this)  page的作用域僅在當前頁面內有效

     config:               jsp的配置資訊

     exception:         代表的是異常資訊物件,只有當 isErrorPage=" true " 時,才有效

JSP的四大作用域:

作用域名 作用範圍 說明
page 僅限當前頁面 從請求到達頁面開始,請求離開這一頁面為止
request 限一次請求 從請求到達伺服器開始,響應返回為止
session 限一次會話 從一個瀏覽器客戶端訪問,伺服器呼叫request.getSession()開始,一直到session.invalidate()或自動超時為止
application 限一次應用執行 從應用程式啟動開始,應用程式結束執行為止

HTTP的無狀態:

        http的無狀態是指請求與請求之間不儲存狀態,即伺服器端不會主動記住上一次請求是誰發的,和這次請求有沒有聯絡。如果伺服器要記住上一次請求的相關資訊,必然需要將這些資訊儲存在伺服器端,增大了伺服器壓力。要知道web應用的一個主要目標是要同時為大量的客戶端提供服務,因此讓伺服器端無狀態,意味著對所有客戶端的處理一視同仁,提高了伺服器的併發能力。(如果需要儲存狀態,可以利用cookie,session等技術來實現

Cookie:用來記錄多次請求之間的聯絡,儲存伺服器的狀態

                    用來 瀏覽器端 儲存伺服器狀態資訊的鍵值對,cookie一般應該 由伺服器 產生

     Cookie的使用:瀏覽器在每次傳送請求時,都會將該域名下的所有Cookie傳送給伺服器

                1) 建立cookie 物件:   Cookie c  =  new Cookie("名字","值"); // 儲存的是鍵值對的資訊

                2)response.addCookie( c ); // 通過響應物件,把建立好的 Cookie  返回給瀏覽器                

                3)c.setMaxAge( 整數 );// 設定Cookie的生存時間,單位是 秒   沒有設定壽命的是會話cookie瀏覽器關閉就刪除

                      c.setMaxAge( 0 );       // 手動刪除此Cookie

     獲取Cookie:

               Cookie[] c = request.getCookies();  // 獲取此次請求中該域名下的所有Cookie

     傳送Cookie時的中文亂碼:

               解決辦法: 編碼:URLEncoder.encode(中文,“utf-8”);  

                                  解碼:URLDecoder.decode(編碼後的內容,"utf-8");

                                  // 前後編碼格式要一致

     EL表示式獲取Cookie的值:

                   語法:  ${cookie.cookie的名字.value};

     Cookie的限制:

                  瀏覽器的每個域名一般包含 30~50 個 Cookie

                  每個Cookie的大小約為 4k

Session: (會話) 可以在同一個客戶端的多次請求間儲存和共享資訊                                     這些資訊被儲存伺服器端  

        session的建立:    

                       // 首次呼叫getSession方法就是建立session物件                        // 後續再呼叫getSession方法是獲取第一次建立好的session物件

                           HttpSession session = req.getSession();

         session的使用: 

                       存入內容:  session.setAttribute("變數名",值);

                       取出內容: Object  o  =  session.getAttribute("變數名");

                       刪除內容: Object  o  =  session.removeAttribute("變數名");

                       使session失效: session.invalidate();  (會清空session的所有內容)

        在JSP頁面中獲取 session 的值:

                        格式:   ${  sessionScope.變數名  }

       session的生命週期:

                       建立: 首次呼叫 request.getSession();  /  request.getSession( true );

                       銷燬:  主動銷燬: session.invalidate();

                                    被動銷燬: session的預設生存時間是 30 分鐘,如果客戶端距離上次請求時間超過此過期時間後,                                                                   tomcat容器會呼叫session.invalidate()方法讓session過期

     ******注意:

  • 關閉瀏覽器並不會立刻結束session,瀏覽器關閉會導致丟失與此session的聯絡                                                       (瀏覽器關閉會刪除JSESSIONID這個會話cookie),因此session還是會在30分鐘後才失效
  • 如何在HttpSession過期的時候,清理你在HttpSession中儲存的物件的資源佔用? 伺服器可以在session過期時自動釋放它所佔用的資源。但如果使用者沒有主動點選登出功能來呼叫session.invalidate()方法,而是直接關閉了瀏覽器,那麼必須再等待一段時間(預設30分鐘)session才會銷燬,比較浪費伺服器資源。 一種解決方法是在客戶端網頁中通過js加入onunload或onbeforeunload事件,此事件會在瀏覽器(或標籤頁)關閉時觸發,這時向伺服器傳送一個登出請求來結束session

Session的實現原理: session必須針對同一個瀏覽器,才能實現在對個請求間共享資訊

                                    每個使用者訪問伺服器時,伺服器會為他們建立一個獨立的session           

                    1)  首次建立 session 物件,伺服器會建立一個 “JESSIONID=值 ” 的 唯一標識 cookie ,

                            隨著 瀏覽器的響應,返回給傳送請求的瀏覽器

                    2)  該瀏覽器拿到此cookie後,之後再次發生請求時會根據這個 cookie 去尋找對應的 session ,由此建立連線

                    3)   JSESSIONID 屬於會話 cookie, 一旦瀏覽器關閉,此cookie就會消失,連線就會中斷

   

URL重寫 :當瀏覽器禁用了Cookie,仍希望能維持會話跟蹤,這時候需要使用URL重寫技術         

  1. 瀏覽器傳送第一次請求給localhost伺服器後,伺服器呼叫request.getSession()建立新的HttpSession物件,假設它的id=123
  2. 當這次響應返回時,需要對頁面中所有表單提交的路徑超連結的路徑之後都加上;jsessionid=123,生成這些路徑字尾可以通過呼叫HttpServletResponse.encodeURL()來完成
  3. 當提交表單請求到達伺服器後,伺服器會解析請求地址後面;jsessionid=123部分,根據它找到正確的HttpSession物件
  4. 當點選超連結請求到達伺服器後,伺服器會解析請求地址後面;jsessionid=123部分,根據它找到正確的HttpSession物件

     

Cookie 和 Session 之間的 聯絡 與 區別:

    cookie 和 session 都是使用 鍵值對 的方式來為 客戶端 儲存一些 伺服器 的資訊     

    區別

               1)cookie是儲存在 瀏覽器端

                      session是儲存在 伺服器端 的 

               2)每個客戶端為某一網站儲存的 cookie 資訊都是有限制的,一般為 30~50 個 cookie,每個大小為 4k 左右

                    而session存在於伺服器端,對儲存的大小沒有限制,但由於伺服器是為多個使用者進行服務的,                                                      所以不建議儲存過多的session資訊,可以將資訊儲存在  資料庫 / 快取 中

               3)安全性: cookie儲存在瀏覽器端很容易被洩露,而且會被截獲的風險很大,而 session就相對更為 安全

               4)生命週期:

                               cookie的生命週期是 在瀏覽器關閉之前都有效

                                session的生命週期則更一些,如果兩次請求之間間隔的時間大於 30 分鐘,則會自動銷燬

                                              或者是 呼叫 session.invalidate() 方法 ,session會立即銷燬

               5)cookie的內容資料型別只能是 字串,而session則可以是 任意型別 的資料

  聯絡: session 與 客戶端 的聯絡 是通過 cookie 實現的

              當伺服器為某一客戶端首次建立session時,會將一個JSESSIONID=唯一值的會話cookie返回給客戶端瀏覽器  ,當瀏覽器向此伺服器傳送接下來的請求時,會攜帶此JSESSIONID=唯一值的cookie,伺服器從而可以通過它找到此客戶端對應的session

請求重定向: response.sendRedirect(" 目標路徑 ")                          

請求轉發: request.getRequestDispatcher(" 目標路徑 ").forword(request,response)

請求轉發 和 重定向的區別

     1) 請求轉發是 同一次請求,跳轉發生在伺服器內部

            重定向 是 兩次請求,第一次請求,伺服器返回一個 302 狀態碼 和  location: 目標地址

                                              第二次請求時,根據返回的 location 的目標地址 跳轉

    2)   請求轉發時,位址列的訪問地址不會改變(還是第一個servlet的訪問地址),轉發地址對瀏覽器是隱藏

           重定向時,位址列的訪問地址會發生改變 (變成最後一個servlet的訪問地址 ),對瀏覽器可見

    3) 因為請求轉發是同一次請求,所以可以利用 request 作用域進行存值,取值

          但是重定向是兩次不同的請求,所以不能利用 request 作用域,但可以使用 session 作用域來存值,取值

    4) 請求轉發的目標只能是本專案的 servlet /  jsp 

          重定向的目標可以是 任意的,既可以是本專案中的 地址,也可以是第三方的地址

*****結論:

  •          當要跳轉的兩個地址關係密切時,使用 請求轉發
  •          當要跳轉的兩個地址關係不密切時,就使用 重定向