From Gossip@caterpillar

JSP/Servlet: session (1)

 

 


session隱含物件在轉換為Servlet之後,對應於 javax.servlet.http.HttpSession型 態之物件, HttpSession負責管理客戶端在瀏覽網站期間的進程(session)資訊,也就是每個操作流程間的狀態維護,您無需知道進程追蹤的細節,就可以 讓使用者在數個頁面之間瀏覽而又能保留相關的進程資訊,例如在幾個頁面之間挑選商品並放入購物車,在最後進行結帳工作。

之前在 Cookie 中介紹過進程追蹤的三種作法,其適用與不適用的場合各不相同。您可以將何時使用何種技術這個工作交給session(HttpSession)物件來負責,相關的實作細節並不太需要您來注意(當然您願意的話,建議您還是瞭解一下會更好)。

舉個例來說,session(HttpSession)會預設使用Cookie來追蹤進程,如果不行(例如使用者關閉Cookie的使用),則您可以試著 使用URL rewriting,或許伺服器會保留一些資訊在伺服器的記憶體或資料庫甚至檔案中,而只傳送session id給客戶端,之後瀏覽器在每個請求中包括這個id,以讓伺服器取出對應的資訊,具體的作法依各家容器的實作而不同。

總而言之,您可以使用session(HttpSession)來協助您作進程追蹤,而不用擔心資訊在伺服端是如何保留的,而session id又是如何產生的。

下面簡單的示範session的使用方式,實作一個簡單的登入網頁,您可以大致瞭解session的使用方式,首先您必須先製作一個簡單的HTML表單,它將用來輸入使用者名稱與密碼:

  • form.htm
<html> 
<head><title>登入頁面</title></head>
<body>
輸入密碼登入:<br>
<form action="login.jsp" method="POST">
名稱:<input type="text" name="user"> <br>
密碼:<input type="password" name="password"> <br>
<input type="submit" value="登入">
</form>
</body>
</html>

接下來撰寫登入驗證頁面login.jsp:
  • login.jsp
<%@page contentType="text/html;charset=Big5"%> 
<%
String user = request.getParameter("user");
String password = request.getParameter("password");
String memberURL =
"http://localhost:8080/myjsp/member.jsp";
String loginFormURL =
"http://localhost:8080/myjsp/form.html";

if(user == null || password == null) {
response.setHeader("Refresh", "0; " + loginFormURL);
}
else if(user.equals("justin") && password.equals("1234")) {
session.setAttribute("user", user);
response.setHeader("Refresh", "3; " + memberURL);
out.println(user + "歡迎登入!3秒後進入會員頁面!");
}
else {
response.setHeader("Refresh", "3; " + loginFormURL);
out.println(
"使用者或密碼錯誤,請重新登入(3秒後回到登入表單)");
}
%>

上面這個頁面在驗證使用者名稱與密碼無誤之後,使用setAttribute()方法,將使用者名稱存入session (HttpSession)物件中,setAttribute()可以存入任何的Java物件,在這邊存入的屬性名稱為"user",存入的物件為 String物件,內容為登入者的名稱,也就是"justin",然後將客戶端重導至會員頁面,如果驗證的結果不正確,就將客戶端重導至登入表單;接下來 撰寫會員頁面member.jsp:
  • member.jsp
<%@page contentType="text/html;charset=Big5"%> 
<%
String loginFormURL =
"http://localhost:8080/myjsp/form.html";
String user = (String) session.getAttribute("user");
if(user == null) {
response.setHeader("Refresh", "3; " + loginFormURL);
out.println(
"喔喔!您還沒登入!不能偷看喔!3秒後進入登入頁面");
}
else {
out.println("嗨!" + user + "!");
out.println("會員好康在這邊。。。。");
// 立即登出
session.invalidate();
}
%>

getAttribute()可以指定屬性名稱取得存在session(HttpSession)中的物件,取回的型態是 Object,為了能夠使用,您必須將之轉換為相對應的型態,在這邊則是String型態,如果之前login.jsp中驗證通過的話,在這個 member.jsp中就可以取得儲存在session中的屬性物件,如果取回的是null,表示之前沒有設定過user屬性,也就是在 login.jsp中沒有通過驗證,我們必須將之送回登入頁面以重新進行登入;invalidate()可以讓目前的session物件失效,我們在 member.jsp中執行這個方法,以實作登出的功能(其實也是為了測試的方便而讓使用者立即登出)。

上面這個例子中,完全沒有牽涉到進程追蹤的實作細節(cookie或是URL rewriting等),一切都是交由session物件來負責,而由於session可以儲存物件資訊,使得進程追蹤所關聯的資訊更為豐富,但卻不用增 加您實作進程追蹤的困難,不過上面這個例子是在瀏覽器的Cookie功能有打開的情況下才能正常運作,如果Cookie沒有開啟,則我們需要作一些額外的 動作,這在下一個主題中討論。

要注意的是,session並不是執行緒安全的,由於session會在客戶端對話期間存在,所以當有多個執行緒會存取session時,必須注意到執行緒安全問題。