一熙涤、cookie機制和session機制的區(qū)別
*************************************************************************************
具體來說cookie機制采用的是在客戶端保持狀態(tài)的方案惋砂,而session機制采用的是在服務器端保持狀態(tài)的方案屑宠。
同時我們也看到厢洞,由于才服務器端保持狀態(tài)的方案在客戶端也需要保存一個標識,所以session
機制可能需要借助于cookie機制來達到保存標識的目的典奉,但實際上還有其他選擇
*************************************************************************************
二躺翻、會話cookie和持久cookie的區(qū)別
*************************************************************************************
如果不設置過期時間,則表示這個cookie生命周期為瀏覽器會話期間卫玖,只要關閉瀏覽器窗口公你,cookie就消失了。這種生命期為瀏覽會話期的cookie被稱為會話cookie假瞬。會話cookie一般不保存在硬盤上而是保存在內(nèi)存里陕靠。
如果設置了過期時間,瀏覽器就會把cookie保存到硬盤上脱茉,關閉后再次打開瀏覽器剪芥,這些cookie依然有效直到超過設定的過期時間。
存儲在硬盤上的cookie可以在不同的瀏覽器進程間共享琴许,比如兩個IE窗口税肪。而對于保存在內(nèi)存的cookie,不同的瀏覽器有不同的處理方式榜田。
*************************************************************************************
三益兄、如何利用實現(xiàn)自動登錄
*************************************************************************************
當用戶在某個網(wǎng)站注冊后,就會收到一個惟一用戶ID的cookie箭券∑客戶后來重新連接時,這個
用戶ID會自動返回邦鲫,服務器對它進行檢查,確定它是否為注冊用戶且選擇了自動登錄神汹,從而使用戶務需給出明確的用戶名和密碼庆捺,就可以訪問服務器上的資源。
*************************************************************************************
四屁魏、如何根據(jù)用戶的愛好定制站點
*************************************************************************************
網(wǎng)站可以使用cookie記錄用戶的意愿滔以。對于簡單的設置,網(wǎng)站可以直接將頁面的設置存儲在cookie中完成定制氓拼。然而對于更復雜的定制你画,網(wǎng)站只需僅將一個惟一的標識符發(fā)送給用戶抵碟,由服務器端的數(shù)據(jù)庫存儲每個標識符對應的頁面設置。
*************************************************************************************
五坏匪、cookie的發(fā)送
*************************************************************************************
1.創(chuàng)建Cookie對象
2.設置最大時效
3.將Cookie放入到HTTP響應報頭
如果你創(chuàng)建了一個cookie拟逮,并將他發(fā)送到瀏覽器,默認情況下它是一個會話級別的cookie:存儲在瀏覽器的內(nèi)存中适滓,用戶退出瀏覽器之后被刪除敦迄。如果你希望瀏覽器將該cookie存儲在磁盤上,則
需要使用maxAge凭迹,并給出一個以秒為單位的時間罚屋。將最大時效設為0則是命令瀏覽器刪除該cookie。
發(fā)送cookie需要使用HttpServletResponse的addCookie方法嗅绸,將cookie插入到一個Set-Cookie HTTP請求報頭中脾猛。由于這個方法并不修改任何之前指定的Set-Cookie報頭,而是創(chuàng)建新的報頭鱼鸠,因此我們將這個方法稱為是addCookie猛拴,而非setCookie。同樣要記住響應報頭必須在任何文檔內(nèi)容發(fā)送到客戶端之前設置瞧柔。
六漆弄、cookie的讀取
*************************************************************************************
1.調(diào)用request.getCookie
要獲取有瀏覽器發(fā)送來的cookie,需要調(diào)用HttpServletRequest的getCookies方法造锅,這個調(diào)用返回Cookie對象的數(shù)組撼唾,對應由HTTP請求中Cookie報頭輸入的值。
2.對數(shù)組進行循環(huán)哥蔚,調(diào)用每個cookie的getName方法倒谷,直到找到感興趣的cookie為止
cookie與你的主機(域)相關,而非你的servlet或JSP頁面糙箍。因而渤愁,盡管你的servlet可能只發(fā)送了單個cookie,你也可能會得到許多不相關的cookie深夯。
例如:
String?cookieName?=?“userID”;
Cookie?cookies[]?=?request.getCookies();
if?(cookies!=null){
for(int?i=0;i
Cookie?cookie?=?cookies[i];
if?(cookieName.equals(cookie.getName())){
doSomethingWith(cookie.getValue());
}
}
}
*************************************************************************************
七抖格、如何使用cookie檢測初訪者
*************************************************************************************
A.調(diào)用HttpServletRequest.getCookies()獲取Cookie數(shù)組
B.在循環(huán)中檢索指定名字的cookie是否存在以及對應的值是否正確
C.如果是則退出循環(huán)并設置區(qū)別標識
D.根據(jù)區(qū)別標識判斷用戶是否為初訪者從而進行不同的操作
*************************************************************************************
八、使用cookie檢測初訪者的常見錯誤
*************************************************************************************
不能僅僅因為cookie數(shù)組中不存在在特定的數(shù)據(jù)項就認為用戶是個初訪者咕晋。如果cookie數(shù)組為null雹拄,客戶可能是一個初訪者,也可能是由于用戶將cookie刪除或禁用造成的結果掌呜。
但是滓玖,如果數(shù)組非null,也不過是顯示客戶曾經(jīng)到過你的網(wǎng)站或域,并不能說明他們曾經(jīng)訪問過你的servlet质蕉。其它servlet势篡、JSP頁面以及非Java?Web應用都可以設置cookie翩肌,依據(jù)路徑的設置,其中的任何cookie都有可能返回給用戶的瀏覽器禁悠。
正確的做法是判斷cookie數(shù)組是否為空且是否存在指定的Cookie對象且值正確念祭。
*************************************************************************************
九、使用cookie屬性的注意問題
*************************************************************************************
屬性是從服務器發(fā)送到瀏覽器的報頭的一部分绷蹲;但它們不屬于由瀏覽器返回給服務器的報頭棒卷。
因此除了名稱和值之外,cookie屬性只適用于從服務器輸出到客戶端的cookie祝钢;服務器端來自于瀏覽器的cookie并沒有設置這些屬性比规。
因而不要期望通過request.getCookies得到的cookie中可以使用這個屬性。這意味著拦英,你不能僅僅通過設置cookie的最大時效蜒什,發(fā)出它,在隨后的輸入數(shù)組中查找適當?shù)腸ookie,讀取它的值疤估,修改它并將它存回Cookie灾常,從而實現(xiàn)不斷改變的cookie值。
*************************************************************************************
十铃拇、如何使用cookie記錄各個用戶的訪問計數(shù)
*************************************************************************************
1.獲取cookie數(shù)組中專門用于統(tǒng)計用戶訪問次數(shù)的cookie的值
2.將值轉換成int型
3.將值加1并用原來的名稱重新創(chuàng)建一個Cookie對象
4.重新設置最大時效
5.將新的cookie輸出
*************************************************************************************
十一钞瀑、session在不同環(huán)境下的不同含義
*************************************************************************************
session,中文經(jīng)常翻譯為會話慷荔,其本來的含義是指有始有終的一系列動作/消息雕什,比如打電話是從拿起電話撥號到掛斷電話這中間的一系列過程可以稱之為一個session。
然而當session一詞與網(wǎng)絡協(xié)議相關聯(lián)時显晶,它又往往隱含了“面向連接”和/或“保持狀態(tài)”這樣兩個含義贷岸。
session在Web開發(fā)環(huán)境下的語義又有了新的擴展,它的含義是指一類用來在客戶端與服務器端之間保持狀態(tài)的解決方案磷雇。有時候Session也用來指這種解決方案的存儲結構偿警。
*************************************************************************************
十二、session的機制
*************************************************************************************
session機制是一種服務器端的機制唯笙,服務器使用一種類似于散列表的結構(也可能就是使用散列表)來保存信息螟蒸。
但程序需要為某個客戶端的請求創(chuàng)建一個session的時候,服務器首先檢查這個客戶端的請求里是否包含了一個session標識-稱為session?id,如果已經(jīng)包含一個session?id則說明以前已經(jīng)為此客戶創(chuàng)建過session崩掘,服務器就按照session?id把這個session檢索出來使用(如果檢索不到七嫌,可能會新建一個,這種情況可能出現(xiàn)在服務端已經(jīng)刪除了該用戶對應的session對象呢堰,但用戶人為地在請求的URL后面附加上一個JSESSION的參數(shù))。
如果客戶請求不包含session?id凡泣,則為此客戶創(chuàng)建一個session并且生成一個與此session相關聯(lián)的session?id枉疼,這個session?id將在本次響應中返回給客戶端保存皮假。
*************************************************************************************
十三、保存session?id的幾種方式
*************************************************************************************
A.保存session?id的方式可以采用cookie骂维,這樣在交互過程中瀏覽器可以自動的按照規(guī)則把這個標識發(fā)送給服務器惹资。
B.由于cookie可以被人為的禁止,必須有其它的機制以便在cookie被禁止時仍然能夠把session?id傳遞回服務器航闺,經(jīng)常采用的一種技術叫做URL重寫褪测,就是把session?id附加在URL路徑的后面,附加的方式也有兩種潦刃,一種是作為URL路徑的附加信息侮措,另一種是作為查詢字符串附加在URL后面。網(wǎng)絡在整個交互過程中始終保持狀態(tài)乖杠,就必須在每個客戶端可能請求的路徑后面都包含這個session?id分扎。
C.另一種技術叫做表單隱藏字段。就是服務器會自動修改表單胧洒,添加一個隱藏字段畏吓,以便在表單提交時能夠把session?id傳遞回服務器。
*************************************************************************************
十四卫漫、session什么時候被創(chuàng)建
*************************************************************************************
一個常見的錯誤是以為session在有客戶端訪問時就被創(chuàng)建菲饼,然而事實是直到某server端程序(如Servlet)調(diào)用HttpServletRequest.getSession(true)這樣的語句時才會被創(chuàng)建。
*************************************************************************************
十五列赎、session何時被刪除
*************************************************************************************
session在下列情況下被刪除:
A.程序調(diào)用HttpSession.invalidate()
B.距離上一次收到客戶端發(fā)送的session?id時間間隔超過了session的最大有效時間
C.服務器進程被停止
再次注意關閉瀏覽器只會使存儲在客戶端瀏覽器內(nèi)存中的session?cookie失效宏悦,不會使服務器端的session對象失效。
*************************************************************************************
十六粥谬、URL重寫有什么缺點
*************************************************************************************
對所有的URL使用URL重寫肛根,包括超鏈接,form的action漏策,和重定向的URL派哲。每個引用你的站點的URL,以及那些返回給用戶的URL(即使通過間接手段掺喻,比如服務器重定向中的Location字段)都要添加額外的信息芭届。
這意味著在你的站點上不能有任何靜態(tài)的HTML頁面(至少靜態(tài)頁面中不能有任何鏈接到站點動態(tài)頁面的鏈接)。因此感耙,每個頁面都必須使用servlet或JSP動態(tài)生成褂乍。即使所有的頁面都動態(tài)生成,如果用戶離開了會話并通過書簽或鏈接再次回來即硼,會話的信息都會丟失逃片,因為存儲下來的鏈接含有錯誤的標識信息-該URL后面的SESSION?ID已經(jīng)過期了。
*************************************************************************************
十七只酥、使用隱藏的表單域有什么缺點
*************************************************************************************
僅當每個頁面都是有表單提交而動態(tài)生成時褥实,才能使用這種方法呀狼。單擊常規(guī)的超文本鏈接并不產(chǎn)生表單提交,因此隱藏的表單域不能支持通常的會話跟蹤损离,只能用于一系列特定的操作中哥艇,比如在線商店的結賬過程
*************************************************************************************
十八、會話跟蹤的基本步驟
*************************************************************************************
1.訪問與當前請求相關的會話對象
2.查找與會話相關的信息
3.存儲會話信息
4.廢棄會話數(shù)據(jù)
*************************************************************************************
十九僻澎、getSession()/getSession(true)貌踏、getSession(false)的區(qū)別
*************************************************************************************
getSession()/getSession(true):當session存在時返回該session,否則新建一個session并返回該對象
getSession(false):當session存在時返回該session窟勃,否則不會新建session祖乳,返回null
*************************************************************************************
二十、如何將信息于會話關聯(lián)起來
*************************************************************************************
setAttribute會替換任何之前設定的值拳恋;如果想要在不提供任何代替的情況下移除某個值凡资,則應使用removeAttribute。這個方法會觸發(fā)所有實現(xiàn)了HttpSessionBindingListener接口的值的valueUnbound
方法谬运。
*************************************************************************************
二十一隙赁、會話屬性的類型有什么限制嗎
*************************************************************************************
通常會話屬性的類型只要是Object就可以了。除了null或基本類型梆暖,如int,double,boolean伞访。
如果要使用基本類型的值作為屬性,必須將其轉換為相應的封裝類對象
*************************************************************************************
二十二轰驳、如何廢棄會話數(shù)據(jù)
*************************************************************************************
A.只移除自己編寫的servlet創(chuàng)建的數(shù)據(jù):
調(diào)用removeAttribute(“key”)將指定鍵關聯(lián)的值廢棄
B.刪除整個會話(在當前Web應用中):
調(diào)用invalidate厚掷,將整個會話廢棄掉。這樣做會丟失該用戶的所有會話數(shù)據(jù)级解,而非僅僅由我們
servlet或JSP頁面創(chuàng)建的會話數(shù)據(jù)
C.將用戶從系統(tǒng)中注銷并刪除所有屬于他(或她)的會話
調(diào)用logOut冒黑,將客戶從Web服務器中注銷,同時廢棄所有與該用戶相關聯(lián)的會話(每個Web應用至多一個)勤哗。這個操作有可能影響到服務器上多個不同的Web應用
*************************************************************************************
二十三抡爹、使用isNew來判斷用戶是否為新舊用戶的錯誤做法
*************************************************************************************
public?boolean?isNew()方法如果會話尚未和客戶程序(瀏覽器)發(fā)生任何聯(lián)系,則這個方法返回true芒划,這一般是因為會話是新建的冬竟,不是由輸入的客戶請求所引起的。
但如果isNew返回false民逼,只不過是說明他之前曾經(jīng)訪問該Web應用泵殴,并不代表他們曾訪問過我們的servlet或JSP頁面。
因為session是與用戶相關的拼苍,在用戶之前訪問的每一個頁面都有可能創(chuàng)建了會話笑诅。因此isNew為false只能說用戶之前訪問過該Web應用,session可以是當前頁面創(chuàng)建,也可能是由用戶之前訪問過的頁面創(chuàng)建的吆你。
正確的做法是判斷某個session中是否存在某個特定的key且其value是否正確
*************************************************************************************
二十四同蜻、Cookie的過期和Session的超時有什么區(qū)別
*************************************************************************************
會話的超時由服務器來維護,它不同于Cookie的失效日期早处。首先,會話一般基于駐留內(nèi)存的cookie
不是持續(xù)性的cookie瘫析,因而也就沒有截至日期砌梆。即使截取到JSESSIONID?cookie,并為它設定一個失效日期發(fā)送出去贬循。瀏覽器會話和服務器會話也會截然不同咸包。
*************************************************************************************
二十五、session?cookie和session對象的生命周期是一樣的嗎
*************************************************************************************
當用戶關閉了瀏覽器雖然session?cookie已經(jīng)消失杖虾,但session對象仍然保存在服務器端
*************************************************************************************
二十六烂瘫、是否只要關閉瀏覽器,session就消失了
*************************************************************************************
程序一般都是在用戶做log?off的時候發(fā)個指令去刪除session奇适,然而瀏覽器從來不會主動在關閉之前通知服務器它將要被關閉坟比,因此服務器根本不會有機會知道瀏覽器已經(jīng)關閉。服務器會一直保留這個會話對象直到它處于非活動狀態(tài)超過設定的間隔為止嚷往。
之所以會有這種錯誤的認識葛账,是因為大部分session機制都使用會話cookie來保存session?id,而關閉瀏覽器后這個session?id就消失了皮仁,再次連接到服務器時也就無法找到原來的session籍琳。
如果服務器設置的cookie被保存到硬盤上,或者使用某種手段改寫瀏覽器發(fā)出的HTTP請求報頭贷祈,把原來的session?id發(fā)送到服務器趋急,則再次打開瀏覽器仍然能夠找到原來的session。
恰恰是由于關閉瀏覽器不會導致session被刪除势誊,迫使服務器為session設置了一個失效時間呜达,當距離客戶上一次使用session的時間超過了這個失效時間時,服務器就可以認為客戶端已經(jīng)停止了活動键科,才會把session刪除以節(jié)省存儲空間闻丑。
由此我們可以得出如下結論:
關閉瀏覽器,只會是瀏覽器端內(nèi)存里的session?cookie消失勋颖,但不會使保存在服務器端的session對象消失嗦嗡,同樣也不會使已經(jīng)保存到硬盤上的持久化cookie消失。
*************************************************************************************
二十七饭玲、打開兩個瀏覽器窗口訪問應用程序會使用同一個session還是不同的session
*************************************************************************************
通常session?cookie是不能跨窗口使用的侥祭,當你新開了一個瀏覽器窗口進入相同頁面時,系統(tǒng)會賦予你一個新的session?id,這樣我們信息共享的目的就達不到了矮冬。
此時我們可以先把session?id保存在persistent?cookie中(通過設置session的最大有效時間)谈宛,然后在新窗口中讀出來,就可以得到上一個窗口的session?id了胎署,這樣通過session?cookie和persistent?cookie的結合我們就可以實現(xiàn)了跨窗口的會話跟蹤吆录。
*************************************************************************************
二十八、如何使用會話顯示每個客戶的訪問次數(shù)
*************************************************************************************
由于客戶的訪問次數(shù)是一個整型的變量琼牧,但session的屬性類型中不能使用int恢筝,double,boolean等基本類型的變量巨坊,所以我們要用到這些基本類型的封裝類型對象作為session對象中屬性的值
但像Integer是一種不可修改(Immutable)的數(shù)據(jù)結構:構建后就不能更改撬槽。這意味著每個請求都必須創(chuàng)建新的Integer對象,之后使用setAttribute來代替之前存在的老的屬性的值趾撵。例如:
HttpSession?session?=?request.getSession();
SomeImmutalbeClass?value?=?(SomeImmutableClass)session.getAttribute(“SomeIdentifier”);
if?(value=?=null){
value?=?new?SomeImmutableClass(…); //?新創(chuàng)建一個不可更改對象
}else{
value?=?new?SomeImmutableClass(calculatedFrom(value));?//?對value重新計算后創(chuàng)建新的對象
}
session.setAttribute(“someIdentifier”,value);?//?使用新創(chuàng)建的對象覆蓋原來的老的對象
*************************************************************************************
二十九侄柔、如何使用會話累計用戶的數(shù)據(jù)
*************************************************************************************
使用可變的數(shù)據(jù)結構,比如數(shù)組占调、List暂题、Map或含有可寫字段的應用程序專有的數(shù)據(jù)結構。通過這種方式究珊,除非首次分配對象敢靡,否則不需要調(diào)用setAttribute。例如
HttpSession?session?=?request.getSession();
SomeMutableClass?value?=?(SomeMutableClass)session.getAttribute(“someIdentifier”);
if(value?=?=?null){
value?=?new?SomeMutableClass(…);
session.setAttribute(“someIdentifier”,value);
}else{
value.updateInternalAttribute(…);?????//?如果已經(jīng)存在該對象則更新其屬性而不需重新設置屬性
}
*************************************************************************************
三十苦银、不可更改對象和可更改對象在會話數(shù)據(jù)更新時的不同處理
*************************************************************************************
不可更改對象因為一旦創(chuàng)建之后就不能更改啸胧,所以每次要修改會話中屬性的值的時候,都需要調(diào)用setAttribute(“someIdentifier”,newValue)來代替原有的屬性的值幔虏,否則屬性的值不會被更新可更改對象因為其自身一般提供了修改自身屬性的方法纺念,所以每次要修改會話中屬性的值的時候,只要調(diào)用該可更改對象的相關修改自身屬性的方法就可以了想括。這意味著我們就不需要調(diào)用setAttribute方法了
*************************************************************************************