Thursday, December 11, 2008

Basics of Filters : Servlet Filters ( Your First Filter )

Overview

Filters are a powerful feature first introduced in version 2.3 of the Servlet API. Filters allow you to write a software component that can then be placed into the request and response flow of a servlet or group of servlets. A filter is not a servlet; filters do not typically create a response to a request but, rather, either modify or inspect the request to a servlet or response from a servlet. Note that you not only can configure filters to act upon servlet requests, but can also apply them to the access of any resource (such as static files).

Like servlets, filters have a specification-defined lifecycle:

§ Filters are initialized by calling their init() method. The init() method is supplied with a FilterConfig object that allows the filter to access initialization parameters as well as reference to the ServletContext.
§ The doFilter() method of the filter is invoked during the request processing of a resource. It is in the doFilter() method that you can inspect the request, modify request headers, modify the response, or skip the processing of the underlying resource altogether.
§ The destroy() method is called when the filter is destroyed.


So what types of filters can you create? The servlet specification gives the following list of suggestions:

§ Authentication filters

§ Logging and auditing filters The first filter you will create in this chapter will log the access of a servlet and supply the elapsed execution time.
§ Image conversion filters Filters can very easily modify the output of a request, such as converting a JPEG image into GIF format.
§ Data compression filters Tomcat supplies the code for a compression filter (named CompressionFilter).
§ Tokenizing filters WML (Wireless Markup Language) is a perfect example of tokenizing; a tokenizing compiler converts tags into a single byte token in an effort to compress the response.
§ Filters that trigger resource access events You may want to log the fact that certain resources are being requested.
§ XSLT filters The last example in this chapter will illustrate the power of using filters to translate XML output into any number of target clients using XSL templates.

What makes a filter a filter?

You must implement the javax.servlet.Filter interface, which includes the init(), doFilter(), and destroy() lifecycle events, and then configure the filter within a web application to place itself into the process chain of a resource request.

Your First Filter

Let’s take a look at a very simple filter that will log the execution time of any requested resource:
package com.omh.filters;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;

/**
* Simple filter for measuring servlet response times
*/
public class ResponseTimerFilter
implements Filter
{
protected FilterConfig config;

public void init(FilterConfig config)
throws ServletException
{
// Save the config object
this.config = config;
}

public void destroy()
{
}

public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws ServletException, IOException
{
// Save the start time
long startTime = System.currentTimeMillis();

// Invoke the next filter/servlet in the chain
chain.doFilter(request, response);

// Capture the elapsed time
long elapsed = System.currentTimeMillis() - startTime;

// Figure out what was requested. If we are not
// processing an HTTP request just default the
// name to servlet
String name = "servlet";
if (request instanceof HttpServletRequest)
{
name = ((HttpServletRequest) request).getRequestURI();
}

// Output the time
config.getServletContext().log(name +
" took " + elapsed + " ms");
}
}


The init() method simply saves a reference to the FilterConfig object (since we’ll use it later to access the ServletContext log() method). There is nothing to do in destroy(), since we don’t have anything to gracefully tear down when the servlet container is done with the filter, but we must provide an empty implementation in order to fully implement the Filter interface.
The doFilter() method is where all the action is found. For our simple ResponseTimeFilter, all we do is save the current clock time, call the next filter in the chain (which will ultimately invoke the requested servlet or resource), and log the elapsed time of the request.

After requesting any resource, the servlet container log file will contain something like the following:
2001-10-28 16:41:07 /jsdg-filters/Properties took 110 ms

In this case, I requested the Properties servlet using Tomcat 4.0. Note that we did nothing to modify the flow or content of the request or response, but this is certainly possible using filters (as we’ll see next).

To notify the servlet container that you have a filter, you must add a filter definition and filter mapping to web.xml:

Timing Filter
com.omh.filters.ResponseTimerFilter



Timing Filter
/*

The element defines the name and fully qualified class name of the filter, while defines a URL pattern that, when matched, will have the corresponding filter placed in its execution stream. A single servlet name can be specified instead, which we’ll use in the last example in the chapter. When using filters that overlap (meaning that more than one filter will be placed in the request chain), the filters will be applied in the same order in which they appear in web.xml.

No comments:

Post a Comment