会话跟踪是一种灵活、轻便的机制,它使在页面上的状态编程变为可能。http是一种无状态协议,每当用户发出请求时,服务器就做出响应,客户端与服务器之间的联系是离散的、非连续的。当用户在同一网站的多个页面之间转换时,根本无法知道是否是同一个客户,会话跟踪就可以解决这个问题。当一个客户在多个页面间切换时,服务器会保存该用户的信息。
在服务器上,通过为在站点上的用户创建一个会话对象保存该用户的信息。当用户第一次访问站点时,分配给用户一个会话对象和一个单独的会话id,这个id是惟一的。在接下来的请求中,会话id标识了这个用户,会话对象作为请求的一部分发送给servlet,servlet能从会话对象中读取信息,或者为其添加信息。
在用户闲置了一段时间后,这个会话对象就失效了,会话对象要被删除,这段时间默认是30分钟,当然可以在系统管理工具中设置这个时间。也可以通过手工操作使会话失效,调用session.invalidate( )方法能使会话对象立即失效,并删除该对象所包含的数据及会话对象本身。
为了使应用具有session功能,java servlet技术提供了管理session的api和集中实现session的机制。java.servlet.http.httpsession就封装了http会话的全部功能,其主要的功能如下。
访问session
session表现为httpsession对象。调用request对象的getsession方法访问session。这个方法返回当前客户端请求(request)所关联的session,如果不存在,则为当前请求(request)创建一个session。由于getsession方法可能会改变响应(response)的头信息,所以需要在获得printwriter或servletoutputstream之前被调用。
使属性和session相关联
可以通过名称使对象值属性和一个session相关联。例如把购物车作为属性存储在session中,在其他servlet中可以通过session再获得购物车。
// 得到用户session和购物篮
httpsession session = request.getsession();
shoppingcart cart = (shoppingcart)session.getattribute("cart");
……
session管理
由于没有办法知道http客户端是否不再需要session,因此每个session都关联一个时间期限使它的资源可以被回收。通过session的setmaxinactiveinterval和getmaxinactiveinterval方法访问超时时间。
为了确保session的有效、不超时,开发人员应该在service方法中周期性地访问session。当客户端完成一个(组)完整的交互过程后,可以使用invalidate()方法使服务器端的session无效,并清除session数据。
// 得到用户session和购物篮
httpsession session = request.getsession();
// 付款完成,使session无效
session.invalidate();
……
实例:会话跟踪servlet程序
下面就举一个关于会话跟踪的具体例子,见示例14-5。
【程序源代码】
1 // ==================== program description ==========================
2 // 程序名称:示例14-5 : sessionservlet.java
3 // 程序目的:编写会话跟踪的servlet程序
4 // ==============================================================
5 package examples.servlets;
6
7 import java.io.*;
8 import java.util.enumeration;
9 import javax.servlet.*;
10 import javax.servlet.http.*;
11
12 public class sessionservlet extends httpservlet
13 {
14 public void doget (httpservletrequest req, httpservletresponse res)
15 throws servletexception, ioexception
16 {
17 httpsession session = req.getsession(true);
18 res.setcontenttype("text/html");
19 printwriter out = res.getwriter();
20 out.println("
+ "sessionservlet output " +
21 "
22 out.println("
bea_button_final_web.gif align=right>");
23 out.println("
sessionservlet output
");24 integer ival = (integer)
session.getattribute("sessiontest.counter");
25 if (ival==null)
26 ival = new integer(1);
27 else
28 ival = new integer(ival.intvalue() + 1);
29 session.setattribute("sessiontest.counter", ival);
30 out.println("you have hit this page
" + ival + " times.
");
31 out.println("click 32 ">here");
33 out.println(" to ensure that session tracking is working even " +
34 "if cookies aren’t supported.
");
35 out.println("note that by default url rewriting is not enabled " +
36 "because of its expensive overhead");
37 out.println("
");
38 out.println("
request and session data:
");39 out.println("session id in request: " +
40 req.getrequestedsessionid());
41 out.println("
session id in request from cookie: " +
42 req.isrequestedsessionidfromcookie());
43 out.println("
session id in request from url: " +
44 req.isrequestedsessionidfromurl());
45 out.println("
valid session id: " +
46 req.isrequestedsessionidvalid());
47 out.println("
session data:
");48 out.println("new session: " + session.isnew());
49 out.println("
session id: " + session.getid());
50 out.println("
creation time: " + session.getcreationtime());
51 out.println("
last accessed time: " +
52 session.getlastaccessedtime());
53
54 out.println("");
55 }
56
57 }
【程序输出结果】如图14-7所示。

图14-7 返回session的信息
【程序注解】
这个程序实现了doget方法,而不是我们经常见到的service方法。第17行用getsession获取会话对象,true表示如果这个会话对象不存在就创建新的。第24行用getattribute( )方法通过session找到与interger相关联的变量。如果不存在这个integer变量,就创建一个整数变量,并用setattribute( )方法将这个整数变量与session相关联;如果存在这个变量,就将整数值加1,表示访问次数增加了。
在向客户端显示信息时,调用了很多session获得属性的方法。getrequestedsessionid()
方法将返回session的id,isrequestedsessionidfromcookie()判断这个request是不是从cookie发出的,isrequestedsessionidfromurl()判断这个request是不是从url发出的,isrequestedsessionidvalid( )方法返回当前请求的session是不是合法。isnew()方法返回这个session是不是新建的。getid()返回session的id,getcreationtime()返回session的创建时间,getlastaccessedtime()返回上次访问时间。
闽公网安备 35060202000074号