鯊魚

          2006年8月29日 #

          lesson 22 under the sea 海底世界

          不久前。。。。。。。。。。

          posted @ 2006-10-26 20:01 無重 閱讀(188) | 評論 (0)編輯 收藏

          HttpSession常見問題

          1、session在何時被創(chuàng)建
          一個常見的誤解是以為session在有客戶端訪問時就被創(chuàng)建,然而事實是直到某server端程序調(diào)用?HttpServletRequest.getSession(true)這樣的語句時才被創(chuàng)建,注意如果JSP沒有顯示的使用?<%?@page?session="false"%>?關(guān)閉session,則JSP文件在編譯成Servlet時將會自動加上這樣一條語句?HttpSession?session?=?HttpServletRequest.getSession(true);這也是JSP中隱含的?session對象的來歷。

          由于session會消耗內(nèi)存資源,因此,如果不打算使用session,應(yīng)該在所有的JSP中關(guān)閉它。

          2、session何時被刪除
          綜合前面的討論,session在下列情況下被刪除a.程序調(diào)用HttpSession.invalidate();或b.距離上一次收到客戶端發(fā)送的session?id時間間隔超過了session的超時設(shè)置;或c.服務(wù)器進程被停止(非持久session)

          3、如何做到在瀏覽器關(guān)閉時刪除session
          嚴(yán)格的講,做不到這一點。可以做一點努力的辦法是在所有的客戶端頁面里使用javascript代碼window.oncolose來監(jiān)視瀏覽器的關(guān)閉動作,然后向服務(wù)器發(fā)送一個請求來刪除session。但是對于瀏覽器崩潰或者強行殺死進程這些非常規(guī)手段仍然無能為力。

          4、有個HttpSessionListener是怎么回事
          你可以創(chuàng)建這樣的listener去監(jiān)控session的創(chuàng)建和銷毀事件,使得在發(fā)生這樣的事件時你可以做一些相應(yīng)的工作。注意是session的創(chuàng)建和銷毀動作觸發(fā)listener,而不是相反。類似的與HttpSession有關(guān)的listener還有?HttpSessionBindingListener,HttpSessionActivationListener和?HttpSessionAttributeListener。

          5、存放在session中的對象必須是可序列化的嗎
          不是必需的。要求對象可序列化只是為了session能夠在集群中被復(fù)制或者能夠持久保存或者在必要時server能夠暫時把session交換出內(nèi)存。在?Weblogic?Server的session中放置一個不可序列化的對象在控制臺上會收到一個警告。我所用過的某個iPlanet版本如果?session中有不可序列化的對象,在session銷毀時會有一個Exception,很奇怪。

          6、如何才能正確的應(yīng)付客戶端禁止cookie的可能性
          對所有的URL使用URL重寫,包括超鏈接,form的action,和重定向的URL,具體做法參見[6]
          http://e-docs.bea.com/wls/docs70/webapp/sessions.html#100770

          7、開兩個瀏覽器窗口訪問應(yīng)用程序會使用同一個session還是不同的session
          參見第三小節(jié)對cookie的討論,對session來說是只認(rèn)id不認(rèn)人,因此不同的瀏覽器,不同的窗口打開方式以及不同的cookie存儲方式都會對這個問題的答案有影響。

          8、如何防止用戶打開兩個瀏覽器窗口操作導(dǎo)致的session混亂
          這個問題與防止表單多次提交是類似的,可以通過設(shè)置客戶端的令牌來解決。就是在服務(wù)器每次生成一個不同的id返回給客戶端,同時保存在session里,客戶端提交表單時必須把這個id也返回服務(wù)器,程序首先比較返回的id與保存在session里的值是否一致,如果不一致則說明本次操作已經(jīng)被提交過了。可以參看《J2EE核心模式》關(guān)于表示層模式的部分。需要注意的是對于使用javascript?window.open打開的窗口,一般不設(shè)置這個id,或者使用單獨的id,以防主窗口無法操作,建議不要再window.open打開的窗口里做修改操作,這樣就可以不用設(shè)置。

          9、為什么在Weblogic?Server中改變session的值后要重新調(diào)用一次session.setValue
          做這個動作主要是為了在集群環(huán)境中提示W(wǎng)eblogic?Server?session中的值發(fā)生了改變,需要向其他服務(wù)器進程復(fù)制新的session值。

          10、為什么session不見了
          排除session正常失效的因素之外,服務(wù)器本身的可能性應(yīng)該是微乎其微的,雖然筆者在iPlanet6SP1加若干補丁的Solaris版本上倒也遇到過;瀏覽器插件的可能性次之,筆者也遇到過3721插件造成的問題;理論上防火墻或者代理服務(wù)器在cookie處理上也有可能會出現(xiàn)問題。
          出現(xiàn)這一問題的大部分原因都是程序的錯誤,最常見的就是在一個應(yīng)用程序中去訪問另外一個應(yīng)用程序。我們在下一節(jié)討論這個問題。

          七、跨應(yīng)用程序的session共享

          常常有這樣的情況,一個大項目被分割成若干小項目開發(fā),為了能夠互不干擾,要求每個小項目作為一個單獨的web應(yīng)用程序開發(fā),可是到了最后突然發(fā)現(xiàn)某幾個小項目之間需要共享一些信息,或者想使用session來實現(xiàn)SSO(single?sign?on),在session中保存login的用戶信息,最自然的要求是應(yīng)用程序間能夠訪問彼此的session。

          然而按照Servlet規(guī)范,session的作用范圍應(yīng)該僅僅限于當(dāng)前應(yīng)用程序下,不同的應(yīng)用程序之間是不能夠互相訪問對方的session的。各個應(yīng)用服務(wù)器從實際效果上都遵守了這一規(guī)范,但是實現(xiàn)的細(xì)節(jié)卻可能各有不同,因此解決跨應(yīng)用程序session共享的方法也各不相同。

          首先來看一下Tomcat是如何實現(xiàn)web應(yīng)用程序之間session的隔離的,從?Tomcat設(shè)置的cookie路徑來看,它對不同的應(yīng)用程序設(shè)置的cookie路徑是不同的,這樣不同的應(yīng)用程序所用的session?id是不同的,因此即使在同一個瀏覽器窗口里訪問不同的應(yīng)用程序,發(fā)送給服務(wù)器的session?id也可以是不同的。


          ??

          根據(jù)這個特性,我們可以推測Tomcat中session的內(nèi)存結(jié)構(gòu)大致如下。




          筆者以前用過的iPlanet也采用的是同樣的方式,估計SunONE與iPlanet之間不會有太大的差別。對于這種方式的服務(wù)器,解決的思路很簡單,實際實行起來也不難。要么讓所有的應(yīng)用程序共享一個session?id,要么讓應(yīng)用程序能夠獲得其他應(yīng)用程序的session?id。

          iPlanet中有一種很簡單的方法來實現(xiàn)共享一個session?id,那就是把各個應(yīng)用程序的cookie路徑都設(shè)為/(實際上應(yīng)該是/NASApp,對于應(yīng)用程序來講它的作用相當(dāng)于根)。
          <session-info>
          <path>/NASApp</path>
          </session-info>

          需要注意的是,操作共享的session應(yīng)該遵循一些編程約定,比如在session?attribute名字的前面加上應(yīng)用程序的前綴,使得?setAttribute("name",?"neo")變成setAttribute("app1.name",?"neo"),以防止命名空間沖突,導(dǎo)致互相覆蓋。


          在Tomcat中則沒有這么方便的選擇。在Tomcat版本3上,我們還可以有一些手段來共享session。對于版本4以上的Tomcat,目前筆者尚未發(fā)現(xiàn)簡單的辦法。只能借助于第三方的力量,比如使用文件、數(shù)據(jù)庫、JMS或者客戶端cookie,URL參數(shù)或者隱藏字段等手段。

          我們再看一下Weblogic?Server是如何處理session的。


          ??

          從截屏畫面上可以看到Weblogic?Server對所有的應(yīng)用程序設(shè)置的cookie的路徑都是/,這是不是意味著在Weblogic?Server中默認(rèn)的就可以共享session了呢?然而一個小實驗即可證明即使不同的應(yīng)用程序使用的是同一個session,各個應(yīng)用程序仍然只能訪問自己所設(shè)置的那些屬性。這說明Weblogic?Server中的session的內(nèi)存結(jié)構(gòu)可能如下




          對于這樣一種結(jié)構(gòu),在?session機制本身上來解決session共享的問題應(yīng)該是不可能的了。除了借助于第三方的力量,比如使用文件、數(shù)據(jù)庫、JMS或者客戶端?cookie,URL參數(shù)或者隱藏字段等手段,還有一種較為方便的做法,就是把一個應(yīng)用程序的session放到ServletContext中,這樣另外一個應(yīng)用程序就可以從ServletContext中取得前一個應(yīng)用程序的引用。示例代碼如下,

          應(yīng)用程序A
          context.setAttribute("appA",?session);?

          應(yīng)用程序B
          contextA?=?context.getContext("/appA");
          HttpSession?sessionA?=?(HttpSession)contextA.getAttribute("appA");?

          值得注意的是這種用法不可移植,因為根據(jù)ServletContext的JavaDoc,應(yīng)用服務(wù)器可以處于安全的原因?qū)τ赾ontext.getContext("/appA");返回空值,以上做法在Weblogic?Server?8.1中通過。

          那么Weblogic?Server為什么要把所有的應(yīng)用程序的cookie路徑都設(shè)為/呢?原來是為了SSO,凡是共享這個session的應(yīng)用程序都可以共享認(rèn)證的信息。一個簡單的實驗就可以證明這一點,修改首先登錄的那個應(yīng)用程序的描述符weblogic.xml,把cookie路徑修改為/appA?訪問另外一個應(yīng)用程序會重新要求登錄,即使是反過來,先訪問cookie路徑為/的應(yīng)用程序,再訪問修改過路徑的這個,雖然不再提示登錄,但是登錄的用戶信息也會丟失。注意做這個實驗時認(rèn)證方式應(yīng)該使用FORM,因為瀏覽器和web服務(wù)器對basic認(rèn)證方式有其他的處理方式,第二次請求的認(rèn)證不是通過?session來實現(xiàn)的。具體請參看[7]?secion?14.8?Authorization,你可以修改所附的示例程序來做這些試驗。

          八、總結(jié)
          session機制本身并不復(fù)雜,然而其實現(xiàn)和配置上的靈活性卻使得具體情況復(fù)雜多變。這也要求我們不能把僅僅某一次的經(jīng)驗或者某一個瀏覽器,服務(wù)器的經(jīng)驗當(dāng)作普遍適用的經(jīng)驗,而是始終需要具體情況具體分析。
          摘要:雖然session機制在web應(yīng)用程序中被采用已經(jīng)很長時間了,但是仍然有很多人不清楚session機制的本質(zhì),以至不能正確的應(yīng)用這一技術(shù)。本文將詳細(xì)討論session的工作機制并且對在Java?web?application中應(yīng)用session機制時常見的問題作出解答。

          posted @ 2006-09-07 10:25 無重 閱讀(439) | 評論 (0)編輯 收藏

          部署問題隨筆

          1 部署時,項目下來框中找不到對應(yīng)的項目的名字,.project的內(nèi)容有誤
          2 部署路徑找不到,是因為缺少.mymetadata文件,修改辦法,點擊項目propertis-》
          ?? webeclipse-web-》context-root中添加項目名 ok


          posted @ 2006-08-29 16:37 無重 閱讀(149) | 評論 (0)編輯 收藏

          主站蜘蛛池模板: 玉林市| 建昌县| 台江县| 西吉县| 固始县| 门头沟区| 张家界市| 资兴市| 永川市| 汕尾市| 濉溪县| 宁安市| 时尚| 宜兰市| 宣恩县| 英超| 若羌县| 凭祥市| 泰州市| 库尔勒市| 山丹县| 宣城市| 吉木萨尔县| 化隆| 芦溪县| 新龙县| 疏附县| 望奎县| 桑植县| 夹江县| 贵德县| 巍山| 陇西县| 马边| 手游| 乐亭县| 辽源市| 乌拉特前旗| 临高县| 沅江市| 海盐县|