会话跟踪是一种灵活、轻便的机制,它使在页面上的状态编程变为可能。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("