Java Web(三) 會話機制,Cookie和Session詳解

    很大一部分應該知道什麼是會話機制,也能說的出幾句,我也大概瞭解一點,可是學了以後幾天不用,立馬忘的一乾二淨,緣由多是沒能好好理解這兩種會話機制,因此會一直遺忘,一直從新回過頭來學習它,今天好好把他總結一下,借鑑該文章中的內容,由於我以爲該篇文章確實寫的很不錯,解答了我不少疑問,特色是對cookie和session的理解,其中的會員卡的例子,真是一針見血的奇效。我按照本身的思路來從新整理一份,給本身之後看。javascript

                                  --WZYjava

 

1、會話機制web

    Web程序中經常使用的技術,用來跟蹤用戶的整個會話。經常使用的會話跟蹤技術是Cookie與Session。Cookie經過在客戶端記錄信息肯定用戶身份Session經過在服務器端記錄信息肯定用戶身份apache

    一次會話指的是:就比如打電話,A給B打電話,接通以後,會話開始,直到掛斷電話,該次會話就結束了,而瀏覽器訪問服務器,就跟打電話同樣,瀏覽器A給服務器發送請求,訪問web程序,該次會話就已經接通,其中無論瀏覽器發送多少請求(就至關於接通電話後說話同樣),都視爲一次會話,直到瀏覽器關閉,本次會話結束。其中注意,一個瀏覽器就至關於一部電話,若是使用火狐瀏覽器,訪問服務器,就是一次會話了,而後打開google瀏覽器,訪問服務器,這是另外一個會話,雖然是在同一臺電腦,同一個用戶在訪問,可是,這是兩次不一樣的會話。api

    知道了什麼是會話後,思考一個問題,一個瀏覽器訪問一個服務器就能創建一個會話,若是別的電腦,都同時訪問該服務器,就會建立不少會話,就拿一些購物網站來講,咱們訪問一個購物網站的服務器,會話就被建立了,而後就點擊瀏覽商品,對感興趣的商品就先加入購物車,等待一塊兒付帳,這看起來是很普通的操做,可是想一下,若是有不少別的電腦上的瀏覽器同時也在訪問該購物網站的服務器,跟咱們作相似的操做呢?服務器又是怎麼記住用戶,怎麼知道用戶A購買的任何商品都應該放在A的購物車內,不管是用戶A什麼時間購買的,不能放入用戶B或用戶C的購物車內的呢?因此就有了cookie和session這兩個技術,就像第一行說的那樣,cookie和session用來跟蹤用戶的整個會話,瀏覽器

     Cookie和Session之間的區別和聯繫tomcat

      假如一個咖啡店有喝5杯咖啡免費贈一杯咖啡的優惠,然而一次性消費5杯咖啡的機會微乎其微,這時就須要某種方式來紀錄某位顧客的消費數量。想象一下其實也無外乎下面的幾種方案:安全

      一、該店的店員很厲害,能記住每位顧客的消費數量,只要顧客一走進咖啡店,店員就知道該怎麼對待了。這種作法就是協議自己支持狀態。可是http協議自己是無狀態的服務器

      二、發給顧客一張卡片,上面記錄着消費的數量,通常還有個有效期限。每次消費時,若是顧客出示這張卡片,則這次消費就會與之前或之後的消費相聯繫起來。這種作法就是在客戶端保持狀態。也就是cookie。 顧客就至關於瀏覽器,cookie如何工做,下面會詳細講解cookie

      三、發給顧客一張會員卡,除了卡號以外什麼信息也不紀錄,每次消費時,若是顧客出示該卡片,則店員在店裏的紀錄本上找到這個卡號對應的紀錄添加一些消費信息。這種作法就是在服務器端保持狀態。

      因爲HTTP協議是無狀態的,而出於種種考慮也不但願使之成爲有狀態的,所以,後面兩種方案就成爲現實的選擇。具體來講cookie機制採用的是在客戶端保持狀態的方案,而session機制採用的是在服務器端保持狀態的方案。同時咱們也看到,因爲採用服務器端保持狀態的方案在客戶端也須要保存一個標識,因此session機制可能須要藉助於cookie機制來達到保存標識的目的,但實際上它還有其餘選擇

 

2、Cookie

     上面已經介紹了爲何要使用Cookie,以及Cookie的一些特色,好比保存在客戶端,用來記錄用戶身份信息的,如今來看看如何使用Cookie。

     藉着上面會員卡的例子來講,採用的是第二種方案,其中還須要解決的問題就是:如何分發會員卡,會員卡的內容,客戶如何使用會員卡,會員卡的有效日期,會員卡的使用範圍

     一、如何分發會員卡、會員卡的內容:也就是cookie是如何建立的?建立後如何發送給客戶端?

        由服務器進行建立,也就至關於咖啡店來建立會員卡,在建立會員卡的同時,就會將會員卡中的內容也給設置了

          Cookie cookie = new Cookie(key,value);  //以鍵值對的方式存放內容,

          response.addCookie(cookie);  //發送回瀏覽器端

        注意:一旦cookie建立好了,就不能在往其中增長別的鍵值對,可是能夠修改其中的內容,

          cookie.setValue();  //將key對應的value值修改

     二、客戶如何使用會員卡,cookie在客戶端是如何工做的,工做原理是什麼?

        

        這個過程就至關於,咖啡店建立好了會員卡,而且已經設置了其中的內容,交到了客戶手中,下次客戶過來時,就帶着會員卡過來,就知道你是會員了,而後咖啡店就拿到你的會員卡對其進行操做。

     三、會員卡的有效日期?也就是cookie也是擁有有效日期的。

        這個能夠自由設置,默認是關閉瀏覽器,cookie就沒用了。

        cookie.setMaxAge(expiry);  //設置cookie被瀏覽器保存的時間。

          expiry:單位秒,默認爲-1,

             expiry=-1:表明瀏覽器關閉後,也就是會話結束後,cookie就失效了,也就沒有了。

             expiry>0:表明瀏覽器關閉後,cookie不會失效,仍然存在。而且會將cookie保存到硬盤中,直到設置時間過時纔會被瀏覽器自動刪除,

             expiry=0:刪除cookie。無論是以前的expiry=-1仍是expiry>0,當設置expiry=0時,cookie都會被瀏覽器給刪除。

    

    四、會員卡的使用範圍?好比星巴克在北京有一個分店,在上海也有一個分店,咱們只是在北京的星巴克辦理了會員卡,那麼當咱們到上海時,就不能使用該會員卡進行打折優惠了。而cookie也是如此,能夠設置服務器端獲取cookie的訪問路徑,而並不是在服務器端的web項目中全部的servlet都能訪問該cookie。

      cookie默認路徑:當前訪問的servlet父路徑。

        例如:http://localhost:8080/test01/a/b/c/SendCookieServlet

          默認路徑:/test01/a/b/c  也就是說,在該默認路徑下的全部Servlet都可以獲取到cookie,/test01/a/b/c/MyServlet 這個MyServlet就能獲取到cookie。

      修改cookie的訪問路徑

        setPath("/");  //在該服務器下,任何項目,任何位置都能獲取到cookie,

          通途:保證在tomcat下全部的web項目能夠共享相同的cookie 

                 例如:tieba , wenku , beike 多個項目共享數據。例如用戶名。

        setPath("/test01/");  //在test01項目下任何位置都能獲取到cookie。

 

    五、總結Cookie:

        工做流程:

          1. servlet建立cookie,保存少許數據,發送瀏覽器。

              2. 瀏覽器得到服務器發送的cookie數據,將自動的保存到瀏覽器端。

                3. 下次訪問時,瀏覽器將自動攜帶cookie數據發送給服務器。

        cookie操做

          1.建立cookie:new Cookie(name,value)

              2.發送cookie到瀏覽器:HttpServletResponse.addCookie(Cookie)

          3.servlet接收cookie:HttpServletRequest.getCookies()  瀏覽器發送的全部cookie

         cookie特色

              1. 每個cookie文件大小:4kb , 若是超過4kb瀏覽器不識別

              2. 一個web站點(web項目):發送20個

                3.一個瀏覽器保存總大小:300個

                4.cookie 不安全,可能泄露用戶信息。瀏覽器支持禁用cookie操做。

              5. 默認狀況生命週期:與瀏覽器會話同樣,當瀏覽器關閉時cookie銷燬的。---臨時cookie

        cookie api

          getName() 得到名稱,cookie中的key

          getValue() 得到值,cookie中的value

          setValue(java.lang.String newValue)  設置內容,用於修改key對應的value值。

          setMaxAge(int expiry) 設置有效時間【】

          setPath(java.lang.String uri)  設置路徑【】  

          setDomain(java.lang.String pattern) 設置域名 , 通常無效,有瀏覽器自動設置,setDomain(".itheima.com")

             www.itheima.com / bbs.itheima.com 均可以訪問

             a.b.itheima.com沒法訪問

             做用:設置cookie的做用範圍,域名+路徑在一塊兒就構成了cookie的做用範圍,上面單獨設置的setPath有用,是由於有瀏覽器自動設置該域名屬性,可是咱們必須知道有這麼個屬性進行域名設置的

          isHttpOnly()  是否只是http協議使用。只能servlet的經過getCookies()得到,javascript不能得到。

          setComment(java.lang.String purpose) (瞭解)  //對該cookie進行描述的信息(說明做用),瀏覽器顯示cookie信息時能看到

          setSecure(boolean flag) (瞭解)  是否使用安全傳輸協議。爲true時,只有當是https請求鏈接時cookie纔會發送給服務器端,而http時不會,可是服務端仍是能夠發送給瀏覽端的。

          setVersion(int v) (瞭解)  參數爲0(傳統Netscape cookie規範編譯)或1(RFC 2109規範編譯)。這個沒用到,不是很懂

        注意:cookie不能發送中文,若是要發送中文,就須要進行特別處理。

          JDK提供工具,進行編碼

            URLEncoder:編碼

            URLDecoder:解碼

            //發送cookie

            Cookie cookie = new Cookie(URLEncoder.encode("哈哈"),URLEncoder.encode("呵呵"));

            response.addCookie(cookie);

            //得到cookie中文內容

            URLDecoder.decoder(request.getCookie().getName);  //獲取key

            URLDecoder.decoder(request.getCookie().getValue);  //獲取value  

     6.cookie案例

         6.一、記住用戶名

            登陸時,在服務器端獲取到用戶名,而後建立一個cookie,將用戶名存入cookie中,發送回瀏覽器端,而後瀏覽器下次在訪問登陸頁面時,先拿到cookie,將cookie中的信息拿出來,看是否保存了該用戶名,若是保存了,那麼直接用他,若是沒有,則本身手寫用戶名。

         6.二、歷史記錄

            好比購物網站,都會有咱們的瀏覽記錄的,實現原理其實也是用cookie技術,每瀏覽一個商品,就將其存入cookie中,到須要顯示瀏覽記錄時,只須要將cookie拿出來遍歷便可。  

 

3、Session

     一樣,會員卡的例子的第三種方法,發給顧客一張會員卡,除了卡號以外什麼信息也不紀錄,每次消費時,若是顧客出示該卡片,則店員在店裏的紀錄本上找到這個卡號對應的紀錄添加一些消費信息。這種作法就是在服務器端保持狀態。 這就是session的用法,在服務器端來保持狀態,保存一些用戶信息。

     功能做用:服務器用於共享數據技術

            

     session原理分析:

        首先瀏覽器請求服務器訪問web站點時,程序須要爲客戶端的請求建立一個session的時候,服務器首先會檢查這個客戶端請求是否已經包含了一個session標識、稱爲SESSIONID,若是已經包含了一個sessionid則說明之前已經爲此客戶端建立過session,服務器就按照sessionid把這個session檢索出來使用,若是客戶端請求不包含session id,則服務器爲此客戶端建立一個session而且生成一個與此session相關聯的session id,sessionid 的值應該是一個既不會重複,又不容易被找到規律以仿造的字符串,這個sessionid將在本次響應中返回到客戶端保存,保存這個sessionid的方式就能夠是cookie,這樣在交互的過程當中,瀏覽器能夠自動的按照規則把這個標識發回給服務器,服務器根據這個sessionid就能夠找獲得對應的session,又回到了這段文字的開始。

     獲取session:

        request.getSession();  //若是沒有將建立一個新的,等效getSession(true);

          有些人不理解,爲何是經過request來獲取session,能夠這樣理解,在獲取session時,須要檢測請求中是否有session標識,因此須要用request來獲取

        request.getSession(boolean);  //true:沒有將建立,false:沒有將返回null

 

     session屬性操做:

        xxxAttribute(...)

          用來存放一些信息,而後才能共享信息 

          setAttrubute(key,value);

          getAttribute(key);

     

     session生命週期

        經常聽到這樣一種誤解「只要關閉瀏覽器,session就消失了」。其實能夠想象一下會員卡的例子,除非顧客主動對店家提出銷卡,不然店家絕對不會輕易刪除顧客的資料。對session來講也是同樣的,除非程序通知服務器刪除一個session,不然服務器會一直保留,程序通常都是在用戶作log off的時候發個指令去刪除session。然而瀏覽器歷來不會主動在關閉以前通知服務器它將要關閉,所以服務器根本不會有機會知道瀏覽器已經關閉,之因此會有這種錯覺,是大部分session機制都使用會話cookie來保存session id,而關閉瀏覽器後這個session id就消失了,再次鏈接服務器時也就沒法找到原來的session。若是服務器設置的cookie被保存到硬盤上,或者使用某種手段改寫瀏覽器發出的HTTP請求頭,把原來的session id發送給服務器,則再次打開瀏覽器仍然可以找到原來的session 

        偏偏是因爲關閉瀏覽器不會致使session被刪除,迫使服務器爲seesion設置了一個失效時間,通常是30分鐘,當距離客戶端上一次使用session的時間超過這個失效時間時,服務器就能夠認爲客戶端已經中止了活動,纔會把session刪除以節省存儲空間

        咱們也能夠本身來控制session的有效時間

          session.invalidate()將session對象銷燬

          setMaxInactiveInterval(int interval) 設置有效時間,單位秒

          在web.xml中配置session的有效時間

            <session-config>

              <session-timeout>30</session-timeout>   單位:分鐘

            <session-config>

    

        因此,討論了這麼就,session的生命週期就是:

            建立:第一次調用getSession()

            銷燬:

               一、超時,默認30分鐘

               二、執行api:session.invalidate()將session對象銷燬、setMaxInactiveInterval(int interval) 設置有效時間,單位秒

               三、服務器非正常關閉

                  自殺,直接將JVM立刻關閉

                  若是正常關閉,session就會被持久化(寫入到文件中,由於session默認的超時時間爲30分鐘,正常關閉後,就會將session持久化,等30分鐘後,就會被刪除)

                  位置: D:\java\tomcat\apache-tomcat-7.0.53\work\Catalina\localhost\test01\SESSIONS.ser

 

     session id的URL重寫

         當瀏覽器將cookie禁用,基於cookie的session將不能正常工做,每次使用request.getSession() 都將建立一個新的session。達不到session共享數據的目的,可是咱們知道原理,只須要將session id 傳遞給服務器session就能夠正常工做的。

        解決:經過URL將session id 傳遞給服務器:URL重寫

          手動方式: url;jsessionid=....

          api方式:

               encodeURL(java.lang.String url) 進行全部URL重寫

               encodeRedirectURL(java.lang.String url) 進行重定向 URL重寫 

               這兩個用法基本一致,只不過考慮特殊狀況,要訪問的連接可能會被Redirect到其餘servlet去進行處理,這樣你用上述方法帶來的session的id信息不能被同時傳送到其餘servlet.這時候用encodeRedirectURL()方法就能夠了 

          若是瀏覽器禁用cooke,api將自動追加session id ,若是沒有禁用,api將不進行任何修改。

          注意:若是瀏覽器禁用cookie,web項目的全部url都需進行重寫。不然session將不能正常工做

        當禁止了cookie時,

                

 

4、總結

    知道了什麼是cookie和什麼是session?

       cookie是一種在客戶端記錄用戶信息的技術,由於http協議是無狀態的,爲了解決這個問題而產生了cookie。記錄用戶名等一些應用

       session是一種在服務端記錄用戶信息的技術,通常session用來在服務器端共享數據,

    cookie的工做原理?session的工做原理?

       cookie工做原理,能夠看上面講解cookie的那張圖,cookie是由服務器端建立發送回瀏覽器端的,而且每次請求服務器都會將cookie帶過去,以便服務器知道該用戶是哪個。其cookie中是使用鍵值對來存儲信息的,而且一個cookie只能存儲一個鍵值對。因此在獲取cookie時,是會獲取到全部的cookie,而後從其中遍歷。

             

       session的工做原理就是依靠cookie來作支撐,第一次使用request.getSession()時session被建立,而且會爲該session建立一個獨一無二的sessionid存放到cookie中,而後發送會瀏覽器端,瀏覽器端每次請求時,都會帶着這個sessionid,服務器就會認識該sessionid,知道了sessionid就找獲得哪一個session。以此來達到共享數據的目的。 這裏須要注意的是,session不會隨着瀏覽器的關閉而死亡,而是等待超時時間。

  

      若是對cookie和session還有不理解的地方,用你們確定都會用,就是須要理解,爲何須要使用cookie和session,能夠看看那個會員卡的例子,cookie和session只是爲了解決http協議無狀態的這種缺陷,爲了記錄用戶信息,記錄瀏覽器和服務器之間的狀態和衍生出來的。

相關文章
相關標籤/搜索