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:
Create a class that extends HttpServletRequestWrapper. 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. 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. Store the filter class in WEB-INF/classes or WEB-INF/lib (if it's in a JAR). 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.
|
No comments:
Post a Comment