Java學(xué)習(xí)

          java,spring,structs,hibernate,jsf,ireport,jfreechart,jasperreport,tomcat,jboss -----本博客已經(jīng)搬家了,新的地址是 http://www.javaly.cn 如果有對(duì)文章有任何疑問(wèn)或者有任何不懂的地方,歡迎到www.javaly.cn (Java樂(lè)園)指出,我會(huì)盡力幫助解決。一起進(jìn)步

           

          HttpSession的正確理解

          關(guān)于HttpSession的誤解實(shí)在是太多了,本來(lái)是一個(gè)很簡(jiǎn)單的問(wèn)題,怎會(huì)搞的如此的復(fù)雜呢?下面說(shuō)說(shuō)我的理解吧:
          一個(gè)session就是一系列某用戶(hù)和服務(wù)器間的通訊。服務(wù)器有能力分辨出不同的用戶(hù)。一個(gè)session的建立是從一個(gè)用戶(hù)向服務(wù)器發(fā)第一個(gè)請(qǐng)求開(kāi)始,而以用戶(hù)顯式結(jié)束或session超時(shí)為結(jié)束。
          其工作原理是這樣的:
          1.當(dāng)一個(gè)用戶(hù)向服務(wù)器發(fā)送第一個(gè)請(qǐng)求時(shí),服務(wù)器為其建立一個(gè)session,并為此session創(chuàng)建一個(gè)標(biāo)識(shí)號(hào);
          2.這個(gè)用戶(hù)隨后的所有請(qǐng)求都應(yīng)包括這個(gè)標(biāo)識(shí)號(hào)。服務(wù)器會(huì)校對(duì)這個(gè)標(biāo)識(shí)號(hào)以判斷請(qǐng)求屬于哪個(gè)session
          這種機(jī)制不使用IP作為標(biāo)識(shí),是因?yàn)楹芏鄼C(jī)器是通過(guò)代理服務(wù)器方式上網(wǎng),沒(méi)法區(qū)分每一臺(tái)機(jī)器。
          對(duì)于session標(biāo)識(shí)號(hào)(sessionID),有兩種方式實(shí)現(xiàn):cookies和URL重寫(xiě)。

          HttpSession的使用
          我們來(lái)看看在API中對(duì)session是如何定義和操作的。
          當(dāng)需要為用戶(hù)端建立一個(gè)session時(shí),servlet容器就創(chuàng)建了一個(gè)HttpSession對(duì)象。其中存儲(chǔ)了和本session相關(guān)的信息。所以,在一個(gè)servlet中有多少個(gè)不同用戶(hù)連接,就會(huì)有多少個(gè)HttpSession對(duì)象。
          使用的機(jī)理是:
          1.從請(qǐng)求中提取HttpSession對(duì)象;
          2.增加或刪除HttpSession中的屬性;
          3.根據(jù)需要關(guān)閉HttpSession或使其失效。

          在請(qǐng)求中有兩個(gè)重載的方法用來(lái)獲取HttpSession對(duì)象。
          HttpSession getSession(boolean create)/getSession();作用是提取HttpSession對(duì)象,如果沒(méi)有自動(dòng)創(chuàng)建。

          獲取到HttpSession對(duì)象后,我們就需要使用HttpSession的某些方法去設(shè)置和更改某些參數(shù)了。如:
          void setAttribute(String name, Object value);
          Object getAttribute(String name);
          void removeAttribute(String name);

          在javax.servlet.http包里一共定義了四個(gè)session監(jiān)聽(tīng)器接口和與之關(guān)聯(lián)的兩個(gè)session事件。分別是:
          HttpSessionAttributeListener and HttpSessionBindingEvent;
          HttpSessionBindingListener and HttpSessionBindingEvent;
          HttpSessionListener and HttpSessionEvent;
          HttpSessionActivationListener and HttpSessionEvent.

          他們的繼承關(guān)系是:
          所有四個(gè)接口的父類(lèi)是java.util.EventListener;
          HttpSessionEvent擴(kuò)展java.util.EventObject;
          而HttpSessionBindingEvent又?jǐn)U展了HttpSessionEvent。

          以下分別詳述:
          HttpSessionAttributeListener
          當(dāng)session中的屬性被添加,更改,刪除時(shí)得到通知。這個(gè)接口上節(jié)講過(guò),主要看其它三個(gè)。

          HttpSessionBindingListener
          當(dāng)一個(gè)實(shí)現(xiàn)了HttpSessionBindingListener的類(lèi)被加入到HttpSession中(或從中移出)時(shí),會(huì)產(chǎn)生HttpBindingEvent事件,而這些事件會(huì)被它本身接收到。
          本接口定義了兩個(gè)方法:
          void valueBound(HttpSessionBindingEvent e);
          void valueUnbound(HttpSessionBindingEvent e);
          當(dāng)多個(gè)實(shí)現(xiàn)了HttpSessionBindingListener的類(lèi)被加入到HttpSession中時(shí),各類(lèi)的方法只對(duì)本類(lèi)感興趣,不會(huì)去理會(huì)其它類(lèi)的加入。
          即使是同一類(lèi)的不同實(shí)例間,也是互不關(guān)心的(各掃門(mén)前雪)。

          我們可以看到前兩個(gè)接口都對(duì)HttpSessionBindingEvent事件做出反應(yīng),但機(jī)理不同。
          HttpSessionAttributeListener是在web.xml中登記的,servlet容器僅創(chuàng)建一個(gè)實(shí)例,來(lái)為任何在session中增加屬性的servlet服務(wù)。觸發(fā)事件的對(duì)象是所有可以轉(zhuǎn)換為Object的實(shí)例。
          HttpSessionBindingListener不用在web.xml中登記,在每個(gè)servlet中用new創(chuàng)建實(shí)例,且僅對(duì)本實(shí)例向session中的加入(或移出)感興趣。觸發(fā)事件的對(duì)象僅僅是自己。

          HttpSessionListener
          對(duì)于session的創(chuàng)建和取消感興趣。需要在web.xml中登記。
          共有兩個(gè)方法:
          void sessionCreated(HttpSessionEvent se);
          void sessionDestroyed(HttpSessionEvent se);
          使用它我們可以容易的創(chuàng)建一個(gè)類(lèi)來(lái)對(duì)session計(jì)數(shù)。


          也許我們會(huì)簡(jiǎn)單的考慮使用sessionDestroyed方法來(lái)在session結(jié)束后做一些清理工作。但是,請(qǐng)注意,當(dāng)這個(gè)方法被調(diào)用的時(shí)候,session已經(jīng)結(jié)束了,你不能從中提取到任何信息了。因此,我們要另辟蹊徑。


          一種通常采用的方法是使用HttpSessionBindingListener接口。在session創(chuàng)建時(shí)增加一個(gè)屬性,而在session結(jié)束前最后一件事將這個(gè)屬性刪除,這樣就會(huì)觸發(fā)valueUnbound方法,所有對(duì)session的清理工作可以在這個(gè)方法中實(shí)現(xiàn)。

          HttpSessionActivationListener
          當(dāng)session在分布式環(huán)境中跨JVM時(shí),實(shí)現(xiàn)該接口的對(duì)象得到通知。共兩個(gè)方法:
          void sessionDidActivate(HttpSessionEvent se);
          void sessionWillPassivate(HttpSessionEvent se);


          1、HTTP協(xié)議本身是“連接-請(qǐng)求-應(yīng)答-關(guān)閉連接”模式的,是一種無(wú)狀態(tài)協(xié)議(HTTP只是一個(gè)傳輸協(xié)議);
          2、Cookie規(guī)范是為了給HTTP增加狀態(tài)跟蹤用的(如果要精確把握,建議仔細(xì)閱讀一下相關(guān)的RFC),但不是唯一的手段;
          3、所謂Session,指的是客戶(hù)端和服務(wù)端之間的一段交互過(guò)程的狀態(tài)信息(數(shù)據(jù));這個(gè)狀態(tài)如何界定,生命期有多長(zhǎng),這是應(yīng)用本身的事情;
          4、由于B/S計(jì)算模型中計(jì)算是在服務(wù)器端完成的,客戶(hù)端只有簡(jiǎn)單的顯示邏輯,所以,Session數(shù)據(jù)對(duì)客戶(hù)端應(yīng)該是透明的不可理解的并且應(yīng)該受控于服務(wù)端;Session數(shù)據(jù)要么保存到服務(wù)端(HttpSession),要么在客戶(hù)端和服務(wù)端之間傳遞(Cookie或url rewritting或Hidden input);
          5、由于HTTP本身的無(wú)狀態(tài)性,服務(wù)端無(wú)法知道客戶(hù)端相繼發(fā)來(lái)的請(qǐng)求是來(lái)自一個(gè)客戶(hù)的,所以,當(dāng)使用服務(wù)端HttpSession存儲(chǔ)會(huì)話(huà)數(shù)據(jù)的時(shí)候客戶(hù)端的每個(gè)請(qǐng)求都應(yīng)該包含一個(gè)session的標(biāo)識(shí)(sid, jsessionid 等等)來(lái)告訴服務(wù)端;
          6、會(huì)話(huà)數(shù)據(jù)保存在服務(wù)端(如HttpSession)的好處是減少了HTTP請(qǐng)求的長(zhǎng)度,提高了網(wǎng)絡(luò)傳輸效率;客戶(hù)端session信息存儲(chǔ)則相反;
          7、客戶(hù)端Session存儲(chǔ)只有一個(gè)辦法:cookie(url rewritting和hidden input因?yàn)闊o(wú)法做到持久化,不算,只能作為交換session id的方式,即a method of session tracking),而服務(wù)端做法大致也是一個(gè)道理:容器有個(gè)session管理器(如tomcat的org.apache.catalina.session包里面的類(lèi)),提供session的生命周期和持久化管理并提供訪(fǎng)問(wèn)session數(shù)據(jù)的api;
          8、使用服務(wù)端還是客戶(hù)端session存儲(chǔ)要看應(yīng)用的實(shí)際情況的。一般來(lái)說(shuō)不要求用戶(hù)注冊(cè)登錄的公共服務(wù)系統(tǒng)(如google)采用cookie做客戶(hù)端session存儲(chǔ)(如google的用戶(hù)偏好設(shè)置),而有用戶(hù)管理的系統(tǒng)則使用服務(wù)端存儲(chǔ)。原因很顯然:無(wú)需用戶(hù)登錄的系統(tǒng)唯一能夠標(biāo)識(shí)用戶(hù)的就是用戶(hù)的電腦,換一臺(tái)機(jī)器就不知道誰(shuí)是誰(shuí)了,服務(wù)端session存儲(chǔ)根本不管用;而有用戶(hù)管理的系統(tǒng)則可以通過(guò)用戶(hù)id來(lái)管理用戶(hù)個(gè)人數(shù)據(jù),從而提供任意復(fù)雜的個(gè)性化服務(wù);
          9、客戶(hù)端和服務(wù)端的session存儲(chǔ)在性能、安全性、跨站能力、編程方便性等方面都有一定的區(qū)別,而且優(yōu)劣并非絕對(duì)(譬如TheServerSide號(hào)稱(chēng)不使用HttpSession,所以性能好,這很顯然:一個(gè)具有上億的訪(fǎng)問(wèn)用戶(hù)的系統(tǒng),要在服務(wù)端數(shù)據(jù)庫(kù)中檢索出用戶(hù)的偏好信息顯然是低效的,Session管理器不管用什么數(shù)據(jù)結(jié)構(gòu)和算法都要耗費(fèi)大量?jī)?nèi)存和CPU時(shí)間;而用cookie,則根本不用檢索和維護(hù)session數(shù)據(jù),服務(wù)器可以做成無(wú)狀態(tài)的,當(dāng)然高效);
          10、所謂的“會(huì)話(huà)cookie”簡(jiǎn)單的說(shuō)就是沒(méi)有明確指明有效期的cookie,僅在瀏覽器當(dāng)前進(jìn)程生命期內(nèi)有效,可以被后繼的Set-Cookie操作清除掉

          posted on 2008-10-16 12:41 找個(gè)美女做老婆 閱讀(3201) 評(píng)論(0)  編輯  收藏


          只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           

          導(dǎo)航

          統(tǒng)計(jì)

          公告

          本blog已經(jīng)搬到新家了, 新家:www.javaly.cn
           http://www.javaly.cn

          常用鏈接

          留言簿(6)

          隨筆檔案

          文章檔案

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 如东县| 济源市| 龙胜| 乐安县| 淅川县| 东阳市| 长治市| 永新县| 安乡县| 报价| 肇州县| 赤水市| 赫章县| 苗栗县| 舟曲县| 额济纳旗| 新宁县| 太白县| 新兴县| 延津县| 义马市| 军事| 宝兴县| 盐亭县| 常州市| 方正县| 凤冈县| 临邑县| 台东县| 永州市| 长武县| 阳谷县| 高青县| 边坝县| 景谷| 栾城县| 平阳县| 武宁县| 大埔县| 文山县| 美姑县|