Counterpublic class Counter extends HttpServlet This servlet maintains an arbitrary set of counter variables and increments
and displays the value of one named counter each time it is invoked. It
saves the state of the counters to a disk file, so the counts are not lost
when the server shuts down. It is suitable for counting page hits, or any
other type of event. It is not typically invoked directly, but is included
within other pages, using JSP, SSI, or a RequestDispatcher |
Fields Summary |
---|
HashMap | counts | File | countfile | long | saveInterval | long | lastSaveTime | public static final String | PARAMETER_NAME | public static final String | ATTRIBUTE_NAME |
Methods Summary |
---|
public void | destroy()
try { saveState(); } // Try to save the state
catch(Exception e) {} // Ignore any problems: we did the best we could
| public void | doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response)This method is called when the servlet is invoked. It looks for a
request parameter named "counter", and uses its value as the name of
the counter variable to increment. If it doesn't find the request
parameter, then it uses the URL of the request as the name of the
counter. This is useful when the servlet is mapped to a URL suffix.
This method also checks how much time has elapsed since it last saved
its state, and saves the state again if necessary. This prevents it
from losing too much data if the server crashes or shuts down without
calling the destroy() method.
// Get the name of the counter as a request parameter
String counterName = request.getParameter(PARAMETER_NAME);
// If we didn't find it there, see if it was passed to us as a
// request attribute, which happens when the output of this servlet
// is included by another servlet
if (counterName == null)
counterName = (String) request.getAttribute(ATTRIBUTE_NAME);
// If it wasn't a parameter or attribute, use the request URL.
if (counterName == null) counterName = request.getRequestURI();
Integer count; // What is the current count?
// This block of code is synchronized because multiple requests may
// be running at the same time in different threads. Synchronization
// prevents them from updating the counts hashtable at the same time
synchronized(counts) {
// Get the counter value from the hashtable
count = (Integer)counts.get(counterName);
// Increment the counter, or if it is new, log and start it at 1
if (count != null) count = new Integer(count.intValue() + 1);
else {
// If this is a counter we haven't used before, send a message
// to the log file, just so we can track what we're counting
log("Starting new counter: " + counterName);
// Start counting at 1!
count = new Integer(1);
}
// Store the incremented (or new) counter value into the hashtable
counts.put(counterName, count);
// Check whether saveInterval milliseconds have elapsed since we
// last saved our state. If so, save it again. This prevents
// us from losing more than saveInterval ms of data, even if the
// server crashes unexpectedly.
if (System.currentTimeMillis() - lastSaveTime > saveInterval) {
saveState();
lastSaveTime = System.currentTimeMillis();
}
} // End of synchronized block
// Finally, output the counter value. Since this servlet is usually
// included within the output of other servlets, we don't bother
// setting the content type.
PrintWriter out = response.getWriter();
out.print(count);
| public void | doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response)
doGet(request, response);
| public void | init()
ServletConfig config = getServletConfig();
try {
// Get the save file.
countfile = new File(config.getInitParameter("countfile"));
// How often should we save our state while running?
saveInterval =
Integer.parseInt(config.getInitParameter("saveInterval"));
// The state couldn't have changed before now.
lastSaveTime = System.currentTimeMillis();
// Now read in the count data
loadState();
}
catch(Exception e) {
// If something goes wrong, wrap the exception and rethrow it
throw new ServletException("Can't init Counter servlet: " +
e.getMessage(), e);
}
| void | loadState()
if (!countfile.exists()) {
counts = new HashMap();
return;
}
ObjectInputStream in = null;
try {
in = new ObjectInputStream(
new BufferedInputStream(new FileInputStream(countfile)));
counts = (HashMap) in.readObject();
}
catch(ClassNotFoundException e) {
throw new IOException("Count file contains bad data: " +
e.getMessage());
}
finally {
try { in.close(); }
catch (Exception e) {}
}
| void | saveState()
ObjectOutputStream out = new ObjectOutputStream(
new BufferedOutputStream(new FileOutputStream(countfile)));
out.writeObject(counts); // Save the hashtable to the stream
out.close(); // Always remember to close your files!
|
|