Servlet Filtering

Filters are a feature that was introduced in version 2.3 of the servlet specification. A filter is a special type of servlet that dynamically intercepts requests and responses and transforms the information contained in them. The main advantage of a filter is that it can be added to existing applications without any need for recompilation.

Filters can have several important uses:

  • To encapsulate recurring tasks in reusable units

  • To format the data sent back to the client

  • To provide authorization and blocking of requests

  • To provide logging and auditing

A filter can perform filtering tasks on the request, the response, or both.

Programming Filters

A filter is still a servlet, so it extends HttpServlet but it also implements the javax.servlet.Filter interface.

Instead of doGet() or doPost(), filter tasks are done in a doFilter() method.

So that a filter can access initialization parameters, it is passed a FilterConfig object in its init() method. A filter can access the ServletContext through the FilterConfig object and thereby load any resources needed for the filtering tasks.

Filters can be connected together in a FilterChain. The servlet container constructs the filter chain in the order the filters appear in the deployment descriptor.

Because filters are added to an application at deploy time, it is possible to map a filter to one or more servlets. This is illustrated in Figure 12.15, where the AuthenticateUser filter is applied to all servlets. The PageCounter is mapped to VerifyData and HTMLPage, and the EncodeResponse filter only affects requests to the AgencyTable servlet.

Figure 12.15. Servlet filter chain.


After a filter successfully completes its task, it must then call the doFilter() method on the next filter in the chain. The filter chain object is passed to the filter by the server as a parameter to the doFilter() method.

public void doFilter(ServletRequest req,ServletResponse res,FilterChain chain)
       throws IOException, ServletException {
  .. // filter code
  chain.doFilter(req, res); // call the next filter in the chain
}

If it is the last filter in the chain, instead of invoking another filter, the container will invoke the resource at the end of the chain (a normal servlet). If for some reason the filter processing fails, and if it is no longer appropriate to continue servicing the request, there is no need to call doFilter() on the next filter in the chain; typically you will forward the request to an error handling page if filter chaining is inappropriate.

In a filter, you must provide an init(FilterConfig) method. This init(FilterConfig) method is called by the Web server when a filter is being placed into service, and it must complete successfully before the filter can do any filtering work.

The destroy() method is called when a filter is being taken out of service, and gives the filter an opportunity to clean up any resources.

The use of these methods will be shown in the following example.

Auditing Filter Example

The filter in Listing 12.8 logs the number of times the application is accessed. A similar technique could be used to intercept requests and authorize the user before calling the servlet to service the request.

Listing 12.8. Servlet Filter
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class AuditFilter extends HttpServlet implements Filter {
  private FilterConfig filterConfig = null;

  public void init(FilterConfig filterConfig)
    throws ServletException {
    this.filterConfig = filterConfig;
  }

  public void destroy() {
    this.filterConfig = null;
  }

  public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
          throws IOException, ServletException {
    if (filterConfig == null)
      return;
    StringBuffer buf = new StringBuffer();
    buf.append ("The number of hits is: ");
    ServletContext ctx = filterConfig.getServletContext();
    synchronized (ctx) {
      Integer counter = (Integer)ctx.getAttribute("Counter");
      if (counter == null)
        counter = new Integer(1);
      else
        counter = new Integer(counter.intValue() + 1);
      buf.append (counter.toString());
      // save the value of the counter in a context attribute
      filterConfig.getServletContext().setAttribute("Counter", counter);
    }
    chain.doFilter(req, res); // call the next filter in the chain
  }
}

Now all that is required is to update the HTMLPage servlet so that it outputs the value of the counter. This new servlet is called HTMLCounterPage and is shown in Listing 12.9.

Listing 12.9. HTMLCounterPage.java Servlet with Counter Added
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class HTMLCounterPage extends HttpServlet {

  public void doGet(HttpServletRequest req, HttpServletResponse res)
         throws ServletException, IOException {
    res.setContentType ("image/gif");
    PrintWriter out = res.getWriter();
    out.println ("<HTML>");
    out.println ("<HEAD><TITLE>Filtered Servlet</TITLE></HEAD>");
    out.println ("<BODY>");
    out.println ("<H1>A Generated HTML Page with a Filter attached</H1>");
    Integer counter = (Integer)getServletContext().getAttribute("Counter");
    out.println ("<P>This page has been accessed "+ counter +" times</P>");
    out.println ("</BODY>");
    out.println ("</HTML>");
  }
}

You can add this servlet to your application examples as described in the next section.

Deploying Filters

Programming the filter is (as always) only half the task. Now it has to be deployed. In J2EE RI, this is achieved with the following steps:

1.
Add your servlet filter to the application examples using the New Web Component Wizard. Add the filter as you would with a normal servlet but you do not need to define an alias because the filter is not mapped onto a URL.

2.
After creating the filter servlet select the Filter Mapping dialogue page for your Web Application and select Edit Filter List and then Add Filter as shown in Figure 12.16.

Figure 12.16. deploytool Adding a Filter.


3.
Returning to the Servlet Filter Mapping page select Add. On the pop-up window select the AuditFilter under Filter Name, select the Filter This Servlet option and set the Servlet Name to be HTMLCounterPage (see Figure 12.17).

Figure 12.17. deploytool Servlet Filter Mapping.


When you view the servlet deployment descriptor, you will see the following lines have been added:

<filter>
 <filter-name>AuditFilter</filter-name>
 <filter-class>AuditFilter</filter-class>
</filter>
<filter-mapping>
 <filter-name>AuditFilter</filter-name>
 <servlet-name>HTMLCounterPage</servlet-name>
</filter-mapping>

4.
Deploy the application and when you access the HTMLCounterPage, the filter maintained counter will be incremented.

This was a very simple example; more sophisticated filters can be used to modify the HTTP request before it is passed to the servlet or modify the HTTP response returned from the servlet.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.222.167.183