ITEEDU

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.html
<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时,必须注意到执行绪安全问题。