FileDocCategorySizeDatePackage
Counter.javaAPI DocExample7317Sat Jan 24 10:44:40 GMT 2004je3.servlet

Counter

public 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
Constructors Summary
Methods Summary
public voiddestroy()

	try { saveState(); }  // Try to save the state
	catch(Exception e) {} // Ignore any problems: we did the best we could
    
public voiddoGet(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 voiddoPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response)

	doGet(request, response);
    
public voidinit()

	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);
	}
    
voidloadState()

	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) {}
	}
    
voidsaveState()

	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!