Friday, November 27, 2009

Recipe 18.3 Using a Filter to Alter Request Headers



[ Team LiB ]






Recipe 18.3 Using a Filter to Alter Request Headers




Problem



You want to use a filter to
change the request headers before a servlet or JSP receives the
request.





Solution



Wrap the request in your own custom request class. Pass the request
wrapper or decorator class to the FilterChain.doFilter(
)

method, instead of the original request
destination.





Discussion



The
javax.servlet.http.HttpServletRequestWrapper is a convenience class that you can
extend to provide additional functionality for an HTTP request. Here
is how to alter and forward a request using a filter:



  1. Create a class that extends
    HttpServletRequestWrapper.

  2. Place this class in the web application's
    WEB-INF/classes (including package-related
    directories) directory or WEB-INF/lib if the
    class is part of a JAR file.

  3. Create a class that implements
    javax.servlet.Filter, such as Example 18-3. This class uses your custom request wrapper
    class to enclose the ServletRequest parameter of
    the Filter.doFilter( ) method.

  4. Store the filter class in WEB-INF/classes or
    WEB-INF/lib (if it's in a JAR).

  5. Register the filter in web.xml. In this recipe,
    the filter is mapped to all of the requests in the web application
    with the URL mapping /*.


Example 18-3 shows the filter class that passes the
request-wrapper class along the filter chain. The file is named
RequestFilter; the wrapper class is named
ReqWrapper.




Example 18-3. A filter that wraps the HttpServletRequest

package com.jspservletcookbook;

import javax.servlet.*;
import javax.servlet.http.*;

public class RequestFilter implements Filter {

private FilterConfig config;

/** Creates new RequestFilter */
public RequestFilter( ) {}

public void init(FilterConfig filterConfig) throws ServletException{

this.config = filterConfig;
}

public void doFilter(ServletRequest request,
ServletResponse response, FilterChain chain) throws java.io.IOException,
ServletException {

ReqWrapper wrapper = null;
ServletContext context = null;

//create the request wrapper object, an instance of the
//ReqWrapper class. The client request is passed into
//ReqWrapper's constructor

if (request instanceof HttpServletRequest)
wrapper = new ReqWrapper((HttpServletRequest)request);


//use the ServletContext.log method to log param names/values

if (wrapper != null){
context = config.getServletContext( );

context.log("Query: " + wrapper.getQueryString( ));}


//continue the request, response to next filter or servlet
//destination

if (wrapper != null)
chain.doFilter(wrapper,response);
else
chain.doFilter(request,response);


}//doFilter

public void destroy( ){

/*called before the Filter instance is removed
from service by the web container*/
}//destroy
}



Example 18-3 uses the servlet context to log the
ReqWrapper's query string. The
ReqWrapper class adds a parameter to the query
string, but you could make this class implement whatever behavior you
need in your own application. Example 18-4 shows the
filter-mapping entries in the deployment
descriptor (web.xml), which ensures that every
application request passes through this filter.




Example 18-4. The filter mapping in web.xml

<filter>

<filter-name>RequestFilter</filter-name>
<filter-class>com.jspservletcookbook.RequestFilter</filter-class>

</filter>

<filter-mapping>

<filter-name>RequestFilter</filter-name>
<url-pattern>/*</url-pattern>

</filter-mapping>



The ReqWrapper
is a simple example of an
HttpServletRequestWrapper subclass that
encapsulates the original request. This class overrides the
getQueryString(
)
method in order to add a parameter to
the request's query string.





To access the new filter parameter, you must call
getQueryString( ) on the request once it reaches
its destination servlet, then parse the getQueryString(
)
return value for individual parameters. Using the EL will
not work with request wrappers that override getQueryString(
)
:




//does not return the new parameter value
//added by the overridden getQueryString
//method
${param.filter}



The request that passes through the filter is the parameter to
ReqWrapper's constructor, so the
filter (in Example 18-3) wraps the request with this
code:



wrapper = new ReqWrapper((HttpServletRequest)request);


A URL sent to the application containing the query string
name=Bruce displays the following text in the
server log (as a result of the
ServletContext.log

method):



 Query: name=Bruce&filter=com.jspservletcookbook.ReqWrapper.


Example 18-5 is the code for the
ReqWrapper object.




Example 18-5. The ReqWrapper class for encapsulating the HttpServletRequest

package com.jspservletcookbook;           

import javax.servlet.*;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletRequest;

public class ReqWrapper extends HttpServletRequestWrapper{

private static final String AMP = "&";

public ReqWrapper(HttpServletRequest request){

super(request);
}

public String getQueryString( ){

String query = null;

//get the query string from the wrapped request object
query = ((HttpServletRequest)getRequest( )).getQueryString( );

//add a 'filter' parameter to this query string with the class
//name as the value
if (query != null)
return query +AMP+"filter="+getClass( ).getName( );
else
return "filter="+getClass( ).getName( );


}//getQueryString
}



The method call chain.doFilter(wrapper,response)
at the end of Example 18-3 passes the request
(wrapped in our own custom class) and response to the next filter, or
to the destination servlet or JSP if no other filters are registered.





See Also



Recipe 18.1 and Recipe 18.2 on examining request
headers in a servlet and a JSP respectively; Recipe 18.3 on using a filter to wrap the request and
forward it along the filter chain; Recipe 18.6 on using a listener to track requests; Chapter 7 on handling request parameters and JavaBean
properties with servlets, JSPs, and filters.








    [ Team LiB ]



    No comments: