Web應用開發中非常重要的主題---會話管理


      由於HTTP的無狀態性,使得會話管理或會話跟蹤成爲Web應用開發一個無可避免的主題。默認下,一個Web服務器無法區分一個HTTP請求是否爲第一次訪問。
      例如,一個Web郵件應用要求用戶登錄後才能查看郵件,因此,當用戶輸入了相應的用戶名和密碼後,應用不應該再次提示需要用戶登錄,應用必須記住哪些用戶已經登錄。換句話說,應用必須能管理用戶的會話。接下來將闡述4中不同的狀態保持技術:URL重寫、隱藏域、cookies和HTTPSession對象。

1.URL重寫

      URL重寫是一種會話跟蹤技術,它將一個或多個token添加到URL的查詢字符串中,每個token通常爲key=value形式,如下:

url?key1=value1&key2=value2...

注意:URL和tokens間用問號(?)分割,token間用與號(&)。
      URL重寫適合於tokens無須在太多URL間傳遞的情況下,然而它有如下限制:

  • URL在某些瀏覽器上最大長度爲2000字符。
  • 若要傳遞值到下一個資源,需要將值插入到鏈接中,換句話說,靜態頁面很難傳值。
  • URL重寫需要在服務端上完成,所有的鏈接都必須帶值,因此當一個頁面存在很多鏈接時,處理過程會是一個不小的挑戰。
  • 某些字符,例如空格、與和問號等必須用base64編碼。
  • 所有的信息都是可見的,某些情況下不合適。

因爲存在如上限制,URL重寫僅適合於信息僅在少量頁面間傳遞,且信息本身不敏感。

2.隱藏域

      使用隱藏域來保持狀態類似於URL重寫技術,但不是將值附加到URL上,而是放到HTML表單的隱藏域中。當表單提交時,隱藏域的值也同時提交到服務器端。隱藏域技術僅當網頁有表單時有效。該技術相對於URL重寫的優勢在於:沒有字符數限制,同時無需額外編碼。但該技術同URL重寫一樣,不適合跨越多個界面。

3.Cookies

      URL重寫和隱藏域僅適合保存無需跨越太多頁面的信息。如果需要在多個頁面間傳遞信息,則以上兩種技術實現成本高昂,因爲你不得不在每個頁面都進行相應處理。幸運的是Cookies技術可以幫到我們。
      Cookies是一個很少的信息片段,可自動地在瀏覽器和Web服務器間交互,因此cookies可存儲在多個頁面間傳遞的信息。Cookie作爲HTTP header的一部分,其傳輸由HTTP協議控制。此外,你可以控制cookie的有效時間。瀏覽器通常支持每個網站高達20個cookies。
      Cookies的問題在於用戶可以通過改變其瀏覽器設置來拒絕接受cookies。要使用cookies,需要熟悉javax.servlet.http.Cookie類以及HttpServletRequest和HttpServletResponse兩個接口。可以通過name和value兩個參數給Cookie類的構造函數來創建一個cookies:

Cookie cookie=new Cookie(name,value);

如下是一個創建語言選擇的cookie示例:

Cookie languageSelectionCookie=new Cookie("language","China");

      創建完一個Cookie對象後,你可以設置domain、path和maxAge屬性。其中,maxAge屬性決定cookie何時過期。要將cookie發送到瀏覽器,需要調用HttpServletResponse的addcookie方法:

httpServletResponse.addCookie(cookie);

      瀏覽器在訪問同一Web服務器時,會將之前收到的cookie一併發送。
      此外,Cookies也可以通過客戶端的javascript腳本創建和刪除。服務端若要讀取瀏覽器提交的cookie,可以通過HttpServletRequest接口的getCookies方法,該方法返回一個Cookie數組,若沒有cookies則返回null。你需要遍歷整個數組來查詢某個特定名稱的cookie。如下爲查詢名爲maxRecords的cookie的示例:

Cookie[] cookies=request.getCookies();
Cookie maxRecordCookie=null;
if(cookies!=null)
{
   for(Cookie cookie:cookies)
   {
      if(cookie.getName().equals("maxRecords"))
      {
        maxRecordCookie=cookie;
        break;
      }
   }
}

      目前,還沒有類似於getCookieByName這樣的方法來幫助簡化工作。此外,也沒有一個直接的方法來刪除cookie,你只能創建一個同名的cookie,並將maxAge屬性設置爲0,並添加到HttpServletResponse接口中。如下爲刪除一個名爲userName的cookie代碼:

Cookie cookie=new Cookie("userName","");
cookie.setMaxAge(0);
response.addCookie(cookie);

4.HttpSession對象

      在所有的會話跟蹤技術中,HttpSession對象時最強大和最通用的。一個用戶可以有且最多有一個HttpSession,並且不會被其他用戶訪問到。HttpSession對象在用戶第一次訪問網站的時候自動被創建,你可以通過調用HttpServletRequest的getSession方法來獲取該對象。getSession有兩個重載方法:

HttpSession getSession()
HttpSession getSession(boolean create)

      沒有參數的getSession方法會返回當前的HttpSession,若當前沒有,則創建一個返回。getSession(false)返回當前HttpSession,如當前會話不存在,則返回null。getSession(true)和getSession()功能一樣。
      可以通過HttpSession的setAttribute方法將值放入HttpSession,將方法簽字如下:

void setAttribute(java.lang.String name,java.lang.Object value)

      請注意,不同於UTL重寫、隱藏域或cookie,放入到HttpSession的值,是存儲在內存中,因此,不要往HttpSession放入太多對象或大對象。儘管現代的Servlet容器在內存不夠用的時候會將保存在HttpSessions的對象轉儲到二級存儲上,但這樣有性能問題,因此小心存儲。
      調用setAttribute方法時,若傳入的name參數此前已經使用過,則會用新值覆蓋舊值。通過調用HttpSession的getAttribute方法可以取回之前放入的對象,該方法的簽名如下:

java.lang.Object getAttribute(java.lang.String name)

      HttpSession還有一個非常有用的方法,名爲getAttributeNames,該方法會返回一個Enumeration對象來迭代訪問保存在HttpSession中的所有值:

java.util.Enumeration<java.lang.String> getAttributeNames()

      注意,所有保存在HttpSession的數據不會被髮送到客戶端,不同於其他會話管理技術,Servlet容器爲每個HttpSession生成唯一的標識,並將該標識發送給瀏覽器,或創建一個名爲JSESSIONID的cookie,或者在URL後附加一個名爲jsessionid的參數。在後續的請求中瀏覽器會將標識提交給服務端,這樣服務器就可以識別該請求時由哪個用戶發起的。Servlet容器會自動選擇一種方式傳遞會話標識,無須開發人員介入。
      可以通過HttpSession的getId方法來讀取該標識:

java.lang.String getId()

      此外,HttpSession還定義了一個名爲invalidate的方法。該方法強制會話過期,並清空其保存對象。默認情況下,HttpSession會在用戶不活動一段時間後自動過期,該時間可以通過部署描述符的session-timeout元素配置,若設置爲30,則會話對象會在用戶最後一次訪問30分鐘後過期,如果部署描述沒有配置,則該值取決於Servlet容器的設定。
      大部分情況下,你應該主動銷燬無用的HttpSession,以便釋放相應的內存。
      可以通過調用HttpSession的getMaxInactiveInterval方法來查看會話多久會過期。該方法返回一個數字類型,單位爲秒。調用setMaxInactiveInterval方法來單獨對某個HttpSession設置器超時時間。

void setMaxInactiveInterval(int seconds)

      若設置爲0,則該HttpSession用不過期。通常這不是一個好的設計,因此該HttpSession所佔用的堆內存將永不釋放,直到應用重加載或Servlet容器關閉。

5.小結

      這4中會話管理技術,URL重寫和隱藏域是輕量級的會話跟蹤技術,適用於那些僅跨少量頁面的數據。而cookies和HttpSession對象,更加靈活但也有限制,尤其是在應用HttpSession時會消耗服務器內存。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章