Session Tracking |
---|
There are three typical solutions to this problem.
Location
fields in server
redirects) has the extra information appended. And, if the user leaves the
session and comes back via a bookmark or link, the session information can
be lost.
<INPUT TYPE="HIDDEN" NAME="session" VALUE="...">
.
This means that, when the form is submitted, the specified name and value
are included in the GET
or POST
data. This can be used to store information
about the session. However, it has the major disadvantage that it only works
if every page is dynamically generated, since the whole point is that each
session has a unique identifier.
HttpSession
API.
This is a high-level interface built on top of cookies or URL-rewriting.
In fact, on many servers, they use cookies if the browser supports them,
but automatically revert to URL-rewriting when cookies are unsupported
or explicitly disabled. But the servlet author doesn't need to bother
with many of the details, doesn't have to explicitly manipulate cookies
or information appended to the URL, and is automatically given a convenient
place to store data that is associated with each session.
getSession
method of
HttpServletRequest
. If this returns null, you can create
a new session, but this is so commonly done that there
is an option to automatically create a new session if there
isn't one already. Just pass true
to getSession
.
Thus, your first step usually looks like this:
HttpSession session = request.getSession(true);
HttpSession
objects live on the server;
they're just automatically associated with the requester by
a behind-the-scenes mechanism like cookies or URL-rewriting.
These session objects have a builtin data structure that let
you store any number of keys and associated values. In version
2.1 and earlier of the servlet API, you use getValue("key")
to
look up a previously stored value. The return type is Object
, so you have
to do a typecast to whatever more specific type of data was associated
with that key in the session. The return value is null
if there is no
such attribute. In version 2.2, getValue
is
deprecated in favor of getAttribute
, both because of the better
naming match with setAttribute
(the match for getValue
is putValue
,
not setValue
), and because setAttribute
lets you use an attached
HttpSessionBindingListener to monitor values, while
putValue
doesn't. Nevertheless, since few commercial servlet
engines yet support version 2.2, I'll use getValue
in my examples.
Here's one representative example, assuming ShoppingCart
is some
class you've defined yourself that stores information on items being purchased.
HttpSession session = request.getSession(true); ShoppingCart previousItems = (ShoppingCart)session.getValue("previousItems"); if (previousItems != null) { doSomethingWith(previousItems); } else { previousItems = new ShoppingCart(...); doSomethingElseWith(previousItems); }In most cases, you have a specific attribute name in mind, and want to find the value (if any) already associated with it. However, you can also discover all the attribute names in a given session by calling
getValueNames
, which returns a String
array. In version 2.2,
use getAttributeNames
, which has a better name and which is more consistent
in that it returns an Enumeration
, just like the getHeaders
and
getParameterNames
methods of HttpServletRequest
.
Although the data that was explicitly associated with a session is the part you care most about, there are some other pieces of information that are sometimes useful as well.
true
if the client (browser) has never seen
the session, usually because it was just created rather than being
referenced by an incoming client request. It returns false
for preexisting
sessions.
Date
constructor or the setTimeInMillis
method
of GregorianCalendar
.
getValue
(or getAttribute
in version 2.2 of the servlet spec). To specify information, you use putValue
(or setAttribute
in version 2.2), supplying a key and a value.
Note that putValue
replaces any previous values. Sometimes
that's what you want (as with the referringPage
entry in the example below),
but other times you want to retrieve a previous value and augment it
(as with the previousItems
entry below). Here's an example:
HttpSession session = request.getSession(true); session.putValue("referringPage", request.getHeader("Referer")); ShoppingCart previousItems = (ShoppingCart)session.getValue("previousItems"); if (previousItems == null) { previousItems = new ShoppingCart(...); } String itemID = request.getParameter("itemID"); previousItems.addEntry(Catalog.getEntry(itemID)); // You still have to do putValue, not just modify the cart, since // the cart may be new and thus not already stored in the session. session.putValue("previousItems", previousItems);
package hall; import java.io.*; import javax.servlet.*; import javax.servlet.http.*; import java.net.*; import java.util.*; /** Simple example of session tracking. See the shopping * cart example for a more detailed one. * <P> * Part of tutorial on servlets and JSP that appears at * http://www.apl.jhu.edu/~hall/java/Servlet-Tutorial/ * 1999 Marty Hall; may be freely used or adapted. */ public class ShowSession extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(true); response.setContentType("text/html"); PrintWriter out = response.getWriter(); String title = "Searching the Web"; String heading; Integer accessCount = new Integer(0);; if (session.isNew()) { heading = "Welcome, Newcomer"; } else { heading = "Welcome Back"; Integer oldAccessCount = // Use getAttribute, not getValue, in version // 2.2 of servlet API. (Integer)session.getValue("accessCount"); if (oldAccessCount != null) { accessCount = new Integer(oldAccessCount.intValue() + 1); } } // Use putAttribute in version 2.2 of servlet API. session.putValue("accessCount", accessCount); out.println(ServletUtilities.headWithTitle(title) + "<BODY BGCOLOR=\"#FDF5E6\">\n" + "<H1 ALIGN=\"CENTER\">" + heading + "</H1>\n" + "<H2>Information on Your Session:</H2>\n" + "<TABLE BORDER=1 ALIGN=CENTER>\n" + "<TR BGCOLOR=\"#FFAD00\">\n" + " <TH>Info Type<TH>Value\n" + "<TR>\n" + " <TD>ID\n" + " <TD>" + session.getId() + "\n" + "<TR>\n" + " <TD>Creation Time\n" + " <TD>" + new Date(session.getCreationTime()) + "\n" + "<TR>\n" + " <TD>Time of Last Access\n" + " <TD>" + new Date(session.getLastAccessedTime()) + "\n" + "<TR>\n" + " <TD>Number of Previous Accesses\n" + " <TD>" + accessCount + "\n" + "</TABLE>\n" + "</BODY></HTML>"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }Here's a typical result, shown after visiting the page several without quitting the browser in between: