9.1. Creating Basic Filters

Creating a filter involves five basic steps:

1.
Create a class that implements the Filter interface. Your class will need three methods: doFilter, init, and destroy. The doFilter method contains the main filtering code (see Step 2), the init method performs setup operations, and the destroy method does cleanup.

2.
Put the filtering behavior in the doFilter method. The first argument to the doFilter method is a ServletRequest object. This object gives your filter full access to the incoming information, including form data, cookies, and HTTP request headers. The second argument is a ServletResponse; it is mostly ignored in simple filters. The final argument is a FilterChain; it is used to invoke the servlet or JSP page as described in the next step.

3.
Call the doFilter method of the FilterChain object. The doFilter method of the Filter interface takes a FilterChain object as one of its arguments. When you call the doFilter method of that object, the next associated filter is invoked. If no other filter is associated with the servlet or JSP page, then the servlet or page itself is invoked.

4.
Register the filter with the appropriate servlets and JSP pages. Use the filter and filter-mapping elements in the deployment descriptor (web.xml).

5.
Disable the invoker servlet. Prevent users from bypassing filter settings by using default servlet URLs.

Details follow.

Create a Class That Implements the Filter Interface

All filters must implement javax.servlet.Filter. This interface comprises three methods: doFilter, init, and destroy.

							public void doFilter(ServletRequest request, 
                     ServletResponse response, FilterChain chain)
							throws ServletException, IOException

The doFilter method is executed each time a filter is invoked (i.e., once for each request for a servlet or JSP page with which the filter is associated). It is this method that contains the bulk of the filtering logic.

The first argument is the ServletRequest associated with the incoming request. For simple filters, most of your filter logic is based on this object. Cast the object to HttpServletRequest if you are dealing with HTTP requests and you need access to methods such as getHeader or getCookies that are unavailable in ServletRequest.

The second argument is the ServletResponse. You often ignore this argument, but there are two cases when you use it. First, if you want to completely block access to the associated servlet or JSP page, you can call response.getWriter and send a response directly to the client. Section 9.7 gives details; Section 9.8 gives an example. Second, if you want to modify the output of the associated servlet or JSP page, you can wrap the response inside an object that collects all output sent to it. Then, after the servlet or JSP page is invoked, the filter can examine the output, modify it if appropriate, and then send it to the client. See Section 9.9 for details.

The final argument to doFilter is a FilterChain object. You call doFilter on this object to invoke the next filter that is associated with the servlet or JSP page. In no other filters are in effect, then the call to doFilter invokes the servlet or JSP page itself.

							public void init(FilterConfig config)
  throws ServletException

The init method is executed only when the filter is first initialized. It is not executed each time the filter is invoked. For simple filters you can provide an empty body to this method, but there are two common reasons for using init. First, the FilterConfig object provides access to the servlet context and to the name of the filter that is assigned in the web.xml file. So, it is common to use init to store the FilterConfig object in a field so that the doFilter method can access the servlet context or the filter name. This process is described in Section 9.3. Second, the FilterConfig object has a getInitParameter method that lets you access filter initialization parameters that are assigned in the deployment descriptor (web.xml). Use of initialization parameters is described in Section 9.5.

public void destroy()

This method is called when a server is permanently finished with a given filter object (e.g., when the server is being shut down). Most filters simply provide an empty body for this method, but it can be used for cleanup tasks like closing files or database connection pools that are used by the filter.

Put the Filtering Behavior in the doFilter Method

The doFilter method is the key part of most filters. Each time a filter is invoked, doFilter is executed. With most filters, the steps that doFilter performs are based on the incoming information. So, you will probably make use of the ServletRequest that is supplied as the first argument to doFilter. This object is frequently typecast to HttpServletRequest to provide access to the more specialized methods of that class.

Call the doFilter Method of the FilterChain Object

The doFilter method of the Filter interface takes a FilterChain object as its third argument. When you call the doFilter method of that object, the next associated filter is invoked. This process normally continues until the last filter in the chain is invoked. When the final filter calls the doFilter method of its FilterChain object, the servlet or page itself is invoked.

However, any filter in the chain can interrupt the process by omitting the call to the doFilter method of its FilterChain. In such a case, the servlet of JSP page is never invoked and the filter is responsible for providing output to the client. For details, see Section 9.7 (Blocking the Response).

Register the Filter with the Appropriate Servlets and JSP Pages

Version 2.3 of the deployment descriptor introduced two elements for use with filters: filter and filter-mapping. The filter element registers a filtering object with the system. The filter-mapping element specifies the URLs to which the filtering object applies.

The filter Element

The filter element goes near the top of deployment descriptor (web.xml), before any filter-mapping, servlet, or servlet-mapping elements. (For more information on the use of the deployment descriptor, see Chapters 4 and 5. For details on the required ordering of elements within the deployment descriptor, see Section 5.2.) The filter element contains six possible subelements:

  • icon. This is an optional element that declares an image file that an IDE can use.

  • filter-name. This is a required element that assigns a name of your choosing to the filter.

  • display-name. This is an optional element that provides a short name for use by IDEs.

  • description. This is another optional element that gives information for IDEs. It provides textual documentation.

  • filter-class. This is a required element that specifies the fully qualified name of the filter implementation class.

  • init-param. This is an optional element that defines initialization parameters that can be read with the getInitParameter method of FilterConfig. A single filter element can contain multiple initparam elements.

Remember that filters were first introduced in version 2.3 of the servlet specification. So, your web.xml file must use version 2.3 of the DTD. Here is a simple example:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<!DOCTYPE web-app PUBLIC 
    "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" 
    "http://java.sun.com/dtd/web-app_2_3.dtd"> 

<web-app> 
  <filter>
								<filter-name>MyFilter</filter-name>
								<filter-class>myPackage.FilterClass</filter-class>
								</filter> 
  <!-- ... --> 
  <filter-mapping>...</filter-mapping> 
</web-app> 

The filter-mapping Element

The filter-mapping element goes in the web.xml file after the filter element but before the servlet element. It contains three possible subelements:

  • filter-name. This required element must match the name you gave to the filter when you declared it with the filter element.

  • url-pattern. This element declares a pattern starting with a slash (/) that designates the URLs to which the filter applies. You must supply url-pattern or servlet-name in all filter-mapping elements. You cannot provide multiple url-pattern entries with a single filter-mapping element, however. If you want the filter to apply to multiple patterns, repeat the entire filter-mapping element.

  • servlet-name. This element gives a name that must match a name given to a servlet or JSP page by means of the servlet element. For details on the servlet element, see Section 5.3 (Assigning Names and Custom URLs). You cannot provide multiple servlet-name elements entries with a single filter-mapping element. If you want the filter to apply to multiple servlet names, repeat the entire filter-mapping element.

Here is a simple example.

<?xml version="1.0" encoding="ISO-8859-1"?> 
<!DOCTYPE web-app PUBLIC 
    "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" 
    "http://java.sun.com/dtd/web-app_2_3.dtd"> 

<web-app> 
  <filter> 
    <filter-name>MyFilter</filter-name> 
    <filter-class>myPackage.FilterClass</filter-class> 
  </filter> 
  <!-- ... --> 
  <filter-mapping>
								<filter-name>MyFilter</filter-name>
								<url-pattern>/someDirectory/SomePage.jsp</url-pattern>
								</filter-mapping> 
</web-app> 

Disable the Invoker Servlet

When you apply filters to resources, you do so by specifying the URL pattern or servlet name to which the filters apply. If you supply a servlet name, that name must match a name given in the servlet element of web.xml. If you use a URL pattern that applies to a servlet, the pattern must match a pattern that you specified with the servlet-mapping web.xml element (see Section 5.3, “ Assigning Names and Custom URLs ”). However, most servers use an “invoker servlet” that provides a default URL for servlets: http://host/webAppPrefix/servlet/ServletName. You need to make sure that users don’t access servlets with this URL, thus bypassing the filter settings.

For example, suppose that you use filter and filter-mapping to say that the filter named SomeFilter applies to the servlet named SomeServlet, as below.

<filter> 
  <filter-name>SomeFilter</filter-name> 
  <filter-class>somePackage.SomeFilterClass</filter-class> 
</filter> 
<!-- ... --> 
<filter-mapping> 
  <filter-name>SomeFilter</filter-name> 
  <servlet-name>SomeServlet</servlet-name> 
</filter-mapping> 

Next, you use servlet and servlet-mapping to stipulate that the URL http://host/webAppPrefix/Blah should invoke SomeServlet, as below.

<servlet> 
  <servlet-name>SomeServlet</servlet-name> 
  <servlet-class>somePackage.SomeServletClass</servlet-class> 
</servlet> 
<!-- ... --> 
<servlet-mapping> 
  <servlet-name>SomeServlet</servlet-name> 
  <url-pattern>/Blah</url-pattern> 
</servlet-mapping> 

Now, the filter is invoked when clients use the URL http://host/webAppPrefix/Blah. No filters apply to http://host/webAppPrefix/servlet/somePackage.SomeServletClass. Oops.

Section 5.4 (Disabling the Invoker Servlet) discusses server-specific approaches to turning off the invoker. The most portable approach, however, is to simply remap the /servlet pattern in your Web application so that all requests that include the pattern are sent to the same servlet. To remap the pattern, you first create a simple servlet that prints an error message or redirects users to the top-level page. Then, you use the servlet and servlet-mapping elements (Section 5.3) to send requests that include the /servlet pattern to that servlet. Listing 9.1 gives a brief example.

Listing 9.1. web.xml (Excerpt that redirects default servlet URLs)
<?xml version="1.0" encoding="ISO-8859-1"?> 
<!DOCTYPE web-app PUBLIC 
    "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" 
    "http://java.sun.com/dtd/web-app_2_3.dtd"> 

<web-app> 
  <!-- ... --> 
  <servlet>
							<servlet-name>Error</servlet-name>
							<servlet-class>somePackage.ErrorServlet</servlet-class>
							</servlet> 
  <!-- ... --> 
  <servlet-mapping>
							<servlet-name>Error</servlet-name>
							<url-pattern>/servlet/*</url-pattern>
							</servlet-mapping> 
  <!-- ... --> 
</web-app> 

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

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