session的機(jī)制
http是無(wú)狀態(tài)的協(xié)議,客戶每次讀取web頁(yè)面時(shí),服務(wù)器都打開新的會(huì)話,而且服務(wù)器也不會(huì)自動(dòng)維護(hù)客戶的上下文信息,那么要怎么才能實(shí)現(xiàn)會(huì)話跟蹤呢?session就是一種保存上下文信息的機(jī)制,它是針對(duì)每一個(gè)用戶的,變量的值保存在服務(wù)器端,通過SessionID來(lái)區(qū)分不同的客戶,session是以cookie或URL重寫為基礎(chǔ)的,默認(rèn)使用cookie來(lái)實(shí)現(xiàn),系統(tǒng)會(huì)創(chuàng)造一個(gè)名為JSESSIONID的輸出返回給客戶端Cookie保存。
保存session id的幾種方式
A.保存sessionid的方式可以采用cookie,這樣在交互過程中瀏覽器可以自動(dòng)的按照規(guī)則把這個(gè)標(biāo)識(shí)發(fā)送給服務(wù)器。
B.由于cookie可以被人為的禁止,必須有其它的機(jī)制以便在cookie被禁止時(shí)仍然能夠把sessionid傳遞回服務(wù)器,經(jīng)常采用的一種技術(shù)叫做URL重寫,就是把sessionid附加在URL路徑的后面,附加的方式也有兩種,一種是作為URL路徑的附加信息,另一種是作為查詢字符串附加在URL后面。網(wǎng)絡(luò)在整個(gè)交互過程中始終保持狀態(tài),就必須在每個(gè)客戶端可能請(qǐng)求的路徑后面都包含這個(gè)sessionid。
C.另一種技術(shù)叫做表單隱藏字段。就是服務(wù)器會(huì)自動(dòng)修改表單,添加一個(gè)隱藏字段,以便在表單提交時(shí)能夠把sessionid傳遞回服務(wù)器。
session何時(shí)被刪除
session在下列情況下被刪除:
A.程序調(diào)用HttpSession.invalidate()
B.距離上一次收到客戶端發(fā)送的sessionid時(shí)間間隔超過了session的最大有效時(shí)間
C.服務(wù)器進(jìn)程被停止
再次注意關(guān)閉瀏覽器只會(huì)使存儲(chǔ)在客戶端瀏覽器內(nèi)存中的sessioncookie失效,不會(huì)使服務(wù)器端的session對(duì)象失效。
URL重寫有什么缺點(diǎn)
對(duì)所有的URL使用URL重寫,包括超鏈接,form的action,和重定向的URL。每個(gè)引用你的站點(diǎn)的URL,以及那些返回給用戶的URL(即使通過間接手段,比如服務(wù)器重定向中的Location字段)都要添加額外的信息。
這意味著在你的站點(diǎn)上不能有任何靜態(tài)的HTML頁(yè)面(至少靜態(tài)頁(yè)面中不能有任何鏈接到站點(diǎn)動(dòng)態(tài)頁(yè)面的鏈接)。因此,每個(gè)頁(yè)面都必須使用servlet或JSP動(dòng)態(tài)生成。即使所有的頁(yè)面都動(dòng)態(tài)生成,如果用戶離開了會(huì)話并通過書簽或鏈接再次回來(lái),會(huì)話的信息都會(huì)丟失,因?yàn)榇鎯?chǔ)下來(lái)的鏈接含有錯(cuò)誤的標(biāo)識(shí)信息-該URL后面的SESSIONID已經(jīng)過期了。
使用隱藏的表單域有什么缺點(diǎn)
僅當(dāng)每個(gè)頁(yè)面都是有表單提交而動(dòng)態(tài)生成時(shí),才能使用這種方法。單擊常規(guī)的<AHREF..>超文本鏈接并不產(chǎn)生表單提交,因此隱藏的表單域只能用于一系列特定的操作中,比如在線商店的結(jié)賬過程。
如何將信息與會(huì)話關(guān)聯(lián)起來(lái)
setAttribute會(huì)替換任何之前設(shè)定的值;如果想要在不提供任何代替的情況下移除某個(gè)值,則應(yīng)使用removeAttribute。這個(gè)方法會(huì)觸發(fā)所有實(shí)現(xiàn)了HttpSessionBindingListener接口的值的valueUnbound方法。
會(huì)話屬性的類型有什么限制嗎
通常會(huì)話屬性的類型只要是Object就可以了。除了null或基本類型,如int,double,boolean。
如果要使用基本類型的值作為屬性,必須將其轉(zhuǎn)換為相應(yīng)的封裝類對(duì)象
使用isNew來(lái)判斷用戶是否為新舊用戶的錯(cuò)誤做法
public booleanisNew()方法如果會(huì)話尚未和客戶程序(瀏覽器)發(fā)生任何聯(lián)系,則這個(gè)方法返回true,這一般是因?yàn)闀?huì)話是新建的,不是由輸入的客戶請(qǐng)求所引起的。
但如果isNew返回false,只不過是說(shuō)明他之前曾經(jīng)訪問該Web應(yīng)用,并不代表他們?cè)L問過我們的servlet或JSP頁(yè)面。
因?yàn)閟ession是與用戶相關(guān)的,在用戶之前訪問的每一個(gè)頁(yè)面都有可能創(chuàng)建了會(huì)話。因此isNew為false只能說(shuō)用戶之前訪問過該Web應(yīng)用,session可以是當(dāng)前頁(yè)面創(chuàng)建,也可能是由用戶之前訪問過的頁(yè)面創(chuàng)建的。
正確的做法是判斷某個(gè)session中是否存在某個(gè)特定的key且其value是否正確
是否只要關(guān)閉瀏覽器,session就消失了
程序一般都是在用戶做logoff的時(shí)候發(fā)個(gè)指令去刪除session,然而瀏覽器從來(lái)不會(huì)主動(dòng)在關(guān)閉之前通知服務(wù)器它將要被關(guān)閉,因此服務(wù)器根本不會(huì)有機(jī)會(huì)知道瀏覽器已經(jīng)關(guān)閉。服務(wù)器會(huì)一直保留這個(gè)會(huì)話對(duì)象直到它處于非活動(dòng)狀態(tài)超過設(shè)定的間隔為止。
之所以會(huì)有這種錯(cuò)誤的認(rèn)識(shí),是因?yàn)榇蟛糠謘ession機(jī)制都使用會(huì)話cookie來(lái)保存session id,而關(guān)閉瀏覽器后這個(gè)sessionid就消失了,再次連接到服務(wù)器時(shí)也就無(wú)法找到原來(lái)的session。
如果服務(wù)器設(shè)置的cookie被保存到硬盤上,或者使用某種手段改寫瀏覽器發(fā)出的HTTP請(qǐng)求報(bào)頭,把原來(lái)的sessionid發(fā)送到服務(wù)器,則再次打開瀏覽器仍然能夠找到原來(lái)的session。
恰恰是由于關(guān)閉瀏覽器不會(huì)導(dǎo)致session被刪除,迫使服務(wù)器為session設(shè)置了一個(gè)失效時(shí)間,當(dāng)距離客戶上一次使用session的時(shí)間超過了這個(gè)失效時(shí)間時(shí),服務(wù)器就可以認(rèn)為客戶端已經(jīng)停止了活動(dòng),才會(huì)把session刪除以節(jié)省存儲(chǔ)空間。
由此我們可以得出如下結(jié)論:
關(guān)閉瀏覽器,只會(huì)是瀏覽器端內(nèi)存里的sessioncookie消失,但不會(huì)使保存在服務(wù)器端的session對(duì)象消失,同樣也不會(huì)使已經(jīng)保存到硬盤上的持久化cookie消失。
如何使用會(huì)話顯示每個(gè)客戶的訪問次數(shù)
由于客戶的訪問次數(shù)是一個(gè)整型的變量,但session的屬性類型中不能使用int,double,boolean等基本類型的變量,所以我們要用到這些基本類型的封裝類型對(duì)象作為session對(duì)象中屬性的值
但像Integer是一種不可修改(Immutable)的數(shù)據(jù)結(jié)構(gòu):構(gòu)建后就不能更改。這意味著每個(gè)請(qǐng)求都必須創(chuàng)建新的Integer對(duì)象,之后使用setAttribute來(lái)代替之前存在的老的屬性的值。例如:
HttpSession session =request.getSession();
SomeImmutalbeClass value =(SomeImmutableClass)session.getAttribute(“SomeIdentifier”);
if (value= =null){
value = new SomeImmutableClass(…); //新創(chuàng)建一個(gè)不可更改對(duì)象
}else{
value = newSomeImmutableClass(calculatedFrom(value)); // 對(duì)value重新計(jì)算后創(chuàng)建新的對(duì)象
}
session.setAttribute(“someIdentifier”,value); //使用新創(chuàng)建的對(duì)象覆蓋原來(lái)的老的對(duì)象
如何使用會(huì)話累計(jì)用戶的數(shù)據(jù)
使用可變的數(shù)據(jù)結(jié)構(gòu),比如數(shù)組、List、Map或含有可寫字段的應(yīng)用程序?qū)S械臄?shù)據(jù)結(jié)構(gòu)。通過這種方式,除非首次分配對(duì)象,否則不需要調(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)存在該對(duì)象則更新其屬性而不需重新設(shè)置屬性
}
愛華網(wǎng)


