HttpSession(在這簡稱session)可以針對特定客戶端(client)保存跨多個請求(request)的狀態,

可以用來儲存客戶端每一次請求時所產生的參數,API中的說明就蠻清楚了

 

下面範例為說明HttpSessionHttpServletRequest的差異,

環境如下

  • Eclipse
  • jdk7
  • tomcat7

 

建立一個動態網站專案(Dynamic Web Project),並新增三個檔案

  • MyServlet_01
  • MyServlet_02
  • index.jsp

 

專案目錄結構如下

在web.xml中Servlet的設定如下...

...

在web.xml中設定了MyServlet_01及MyServlet_02兩個Servlet及其url mapping。

 

MyServlet_01...

...

點選index.jsp的MyServlet_01的連結會送出請求到Container,接著Container會轉交給MyServet_01.java的doGet()方法。

在doGet()中設定了request的屬性"name",其值為"Matt"設定了session的屬性"name",其值為"Phoebe"

最後將request及response轉交給index.jsp。

 

MyServlet_02...

...

點擊index.jsp的MyServlet_02連結,會送出請求給Container,Container會將request轉交(forward)給MyServlet_02.java的doGet(),在doGet()中,企圖從request取出名為"name"的屬性,及企圖從session中取出名為"name"的屬性(因為不論從requestsession物件取出屬性時,都會回傳Object型態的物件,因為當初存入的分別是字串"Matt"及"Phoebe",所以取出時要用(String)來轉型回為字串),並將取出的結果印出,最後返回index.jsp。

 

index.jsp...

...

 

上面三個檔案都建立好後,啟動Tomcat並開啟index.jsp頁面。

index.jsp開啟後先點選MyServlet_01這個連結來呼叫MyServlet_01這支Servlet,

 

點選後可以在Eclipse的Console看到如下訊息。

 

在MyServlet_01的doGet()方法中最後會將請求轉交回給index.jsp,所以畫面又會回到index.jsp(所以在點選MyServlet_01的連結瞬間你會看到index.jsp的畫面有閃一下),

此時再點選MyServlet_02這條連結來呼叫MyServlet_02這支Servlet

 

然後會執行MySerlvet_02的doGet()中的程式碼,並印出以下訊息。

可以看到雖然在MyServlet_01中有加入了request屬性"name",但在MyServlet_02取出的值卻為null,但在MyServlet_01中加入的session屬性"name"的值"Phoebe"有被印出來。

在此範例中,客戶端一共發出了兩個request,先後分別呼叫了MyServlet_01及MyServlet_02。

可以看到session屬性的狀態可以保留至第二次發給MyServlet_02的請求。但相反地,request的屬性狀態就無法如session一樣在第二次的請求中取得了,因為每一次客戶端的請求對Container來說都是新的request,也就是說,在MyServlet_01和MyServlet_02中的request並不是同一個request,所以在MyServlet_02中的request當然就沒有名稱為"name"這個屬性了。

那為什麼Container會認得session呢,因為當客戶端發出第一個request給Container時,Container就會默默地為此次連線建立一個session id並紀錄起來,然後將session id存放在回應給客戶端的response物件中,當下一次客戶端再送出新的request時,瀏覽器會將session id一起送給Container,當Container檢查到這個request中的session id與先前紀錄的session id相同,就會認得這次的請求的session了。

又Container會對不同客戶端的連線建立專屬的session及執行緒(thread),所以就可以區分來自不同客戶端的請求了,因此不同客戶端的session不會被混在一起,所以session可用來處理身分識別的工作。

但session是非執行緒安全的(non thread-safe),所以操作來自同個客戶端的session物件時要留意此問題。

另外初學者常混淆的地方,就是加入session的"name"屬性和加入request的"name"屬性雖然都叫做"name",但一個是儲存在session物件中的"name",一個是存在request物件的"name",這也是範例中刻意兩者都用"name"的原因。

 

除了session,雖然也可將客戶端每一次請求所產生的參數存放於資料庫(例如MySQL)中來達到保存對話狀態的目的,但這樣的做法非常影響效能,用起來也非常麻煩,所以最好的做法還是將狀態暫存在Session中是比較好的選擇。

 

參考:深入淺出Servlets與JSP(Head First Servlets and JSP)

 

 

 

創作者介紹

菲比傻大姐&肉豬

phoebelin0606 發表在 痞客邦 PIXNET 留言(0) 人氣()