Main Concepts in Filtering
The main concepts of this filtering model are described in this section.
The application developer creates a filter by implementing the javax.servlet.Filter interface and providing a public constructor taking no arguments. The class is packaged in theWeb Archive along with the static content and servlets that make up the Web application. A filter is declared using the <filter> element in the deployment descriptor. A filter or collection of filters can be configured for invocation by defining <filter-mapping> elements in the deployment descriptor. This is done by mapping filters to a particular servlet by the servlet’s logical name, or mapping to a group of servlets and static content resources by mapping a filter to a URL pattern.
The application developer creates a filter by implementing the javax.servlet.Filter interface and providing a public constructor taking no arguments. The class is packaged in theWeb Archive along with the static content and servlets that make up the Web application. A filter is declared using the <filter> element in the deployment descriptor. A filter or collection of filters can be configured for invocation by defining <filter-mapping> elements in the deployment descriptor. This is done by mapping filters to a particular servlet by the servlet’s logical name, or mapping to a group of servlets and static content resources by mapping a filter to a URL pattern.
=> Filter Lifecycle
After deployment of the Web application, and before a request causes the container to access a Web resource, the container must locate the list of filters that must be applied to the Web resource as described below. The container must ensure that it has instantiated a filter of the appropriate class for each filter in the list, and called its init(FilterConfig config) method. The filter may throw an exception to indicate that it cannot function properly. If the exception is of type UnavailableException, the container may examine the isPermanent attribute of the exception and may choose to retry the filter at some later time.
Only one instance per <filter> declaration in the deployment descriptor is instantiated per Java Virtual Machine (JVMTM) of the container. The container provides the filter config as declared in the filter’s deployment descriptor, the reference to the ServletContext for the Web application, and the set of initialization parameters.
When the container receives an incoming request, it takes the first filter instance in the list and calls its doFilter method, passing in the ServletRequest and ServletResponse, and a reference to the FilterChain object it will use.
Only one instance per <filter> declaration in the deployment descriptor is instantiated per Java Virtual Machine (JVMTM) of the container. The container provides the filter config as declared in the filter’s deployment descriptor, the reference to the ServletContext for the Web application, and the set of initialization parameters.
When the container receives an incoming request, it takes the first filter instance in the list and calls its doFilter method, passing in the ServletRequest and ServletResponse, and a reference to the FilterChain object it will use.
The doFilter method of a filter will typically be implemented following this or some subset of the following pattern:
Step 1: The method examines the request’s headers.
Step 2: The method may wrap the request object with a customized implementation of ServletRequest or HttpServletRequest in order to modify request headers or data.
Step 3: The method may wrap the response object passed in to its doFilter method with a customized implementation of ServletResponse or HttpServletResponse to modify response headers or data.
Step 4: The filter may invoke the next entity in the filter chain. The next entity may be another filter, or if the filter making the invocation is the last filter configured in the deployment descriptor for this chain, the next entity is the target Web resource. The invocation of the next entity is effected by calling the doFilter method on the FilterChain object, and passing in the request and response with which it was called or passing in wrapped versions it may have created.
The filter chain’s implementation of the doFilter method, provided by the container, must locate the next entity in the filter chain and invoke its doFilter method, passing in the appropriate request and response objects.
Alternatively, the filter chain can block the request by not making the call to invoke the next entity, leaving the filter responsible for filling out the response object.
Step 5: After invocation of the next filter in the chain, the filter may examine response headers.
Step 6: Alternatively, the filter may have thrown an exception to indicate an error in processing. If the filter throws an UnavailableException during its doFilter processing, the container must not attempt continued processing down the filter chain. It may choose to retry the whole chain at a later time if the exception is not marked permanent.
Step 7: When the last filter in the chain has been invoked, the next entity accessed is the target servlet or resource at the end of the chain.
Step 1: The method examines the request’s headers.
Step 2: The method may wrap the request object with a customized implementation of ServletRequest or HttpServletRequest in order to modify request headers or data.
Step 3: The method may wrap the response object passed in to its doFilter method with a customized implementation of ServletResponse or HttpServletResponse to modify response headers or data.
Step 4: The filter may invoke the next entity in the filter chain. The next entity may be another filter, or if the filter making the invocation is the last filter configured in the deployment descriptor for this chain, the next entity is the target Web resource. The invocation of the next entity is effected by calling the doFilter method on the FilterChain object, and passing in the request and response with which it was called or passing in wrapped versions it may have created.
The filter chain’s implementation of the doFilter method, provided by the container, must locate the next entity in the filter chain and invoke its doFilter method, passing in the appropriate request and response objects.
Alternatively, the filter chain can block the request by not making the call to invoke the next entity, leaving the filter responsible for filling out the response object.
Step 5: After invocation of the next filter in the chain, the filter may examine response headers.
Step 6: Alternatively, the filter may have thrown an exception to indicate an error in processing. If the filter throws an UnavailableException during its doFilter processing, the container must not attempt continued processing down the filter chain. It may choose to retry the whole chain at a later time if the exception is not marked permanent.
Step 7: When the last filter in the chain has been invoked, the next entity accessed is the target servlet or resource at the end of the chain.
Step 8: Before a filter instance can be removed from service by the container, the container must first call the destroy method on the filter to enable the filter to release any resources and perform other cleanup
operations.
operations.
=> Wrapping Requests and Responses
Central to the notion of filtering is the concept of wrapping a request or response in order that it can override behavior to perform a filtering task. In this model, the developer not only has the ability to override existing methods on the request and response objects, but to provide new API suited to a particular filtering task to a filter or target web resource down the chain. For example, the developer may wish to extend the response object with higher level output objects that the output stream or the writer, such as API that allows DOM objects to be written back to the client.
In order to support this style of filter the container must support the following requirement. When a filter invokes the doFilter method on the container’s filter chain implementation, the container must ensure that the request and response object that it passes to the next entity in the filter chain, or to the target web resource if the filter was the last in the chain, is the same object that was passed into the doFilter method by the calling filter.
The same requirement of wrapper object identity applies to the calls from a servlet or a filter to RequestDispatcher.forward or RequestDispatcher.include, when the caller wraps the request or response objects. In this case, the request and response objects seen by the called servlet must be the same wrapper objects that were passed in by the calling servlet or filter.
In order to support this style of filter the container must support the following requirement. When a filter invokes the doFilter method on the container’s filter chain implementation, the container must ensure that the request and response object that it passes to the next entity in the filter chain, or to the target web resource if the filter was the last in the chain, is the same object that was passed into the doFilter method by the calling filter.
The same requirement of wrapper object identity applies to the calls from a servlet or a filter to RequestDispatcher.forward or RequestDispatcher.include, when the caller wraps the request or response objects. In this case, the request and response objects seen by the called servlet must be the same wrapper objects that were passed in by the calling servlet or filter.
=> Filter Environment
A set of initialization parameters can be associated with a filter using the <initparams> element in the deployment descriptor. The names and values of these parameters are available to the filter at runtime via the getInitParameter and getInitParameterNames methods on the filter’s FilterConfig object. Additionally,
the FilterConfig affords access to the ServletContext of the Web application for the loading of resources, for logging functionality, and for storage of state in the ServletContext’s attribute list.
the FilterConfig affords access to the ServletContext of the Web application for the loading of resources, for logging functionality, and for storage of state in the ServletContext’s attribute list.
=> Configuration of Filters in a Web Application
A filter is defined in the deployment descriptor using the <filter> element. In this element, the programmer declares the following:
=> filter-name: used to map the filter to a servlet or URL
=> filter-class: used by the container to identify the filter type
=> init-params: initialization parameters for a filter
Optionally, the programmer can specify icons, a textual description, and a display name for tool manipulation. The container must instantiate exactly one instance of the Java class defining the filter per filter declaration in the deployment descriptor. Hence, two instances of the same filter class will be instantiated by the container if the developer makes two filter declarations for the same filter class.
=> filter-name: used to map the filter to a servlet or URL
=> filter-class: used by the container to identify the filter type
=> init-params: initialization parameters for a filter
Optionally, the programmer can specify icons, a textual description, and a display name for tool manipulation. The container must instantiate exactly one instance of the Java class defining the filter per filter declaration in the deployment descriptor. Hence, two instances of the same filter class will be instantiated by the container if the developer makes two filter declarations for the same filter class.
Here is an example of a filter declaration:
<filter>
<filter-name>Image Filter</filter-name>
<filter-class>com.acme.ImageServlet</filter-class>
</filter>
Once a filter has been declared in the deployment descriptor, the assembler uses the <filter-mapping> element to define servlets and static resources in the Web application to which the filter is to be applied. Filters can be associated with a servlet using the <servlet-name> element. For example, the following code example maps the Image Filter filter to the ImageServlet servlet:
<filter-mapping>
<filter-name>Image Filter</filter-name>
<servlet-name>ImageServlet</servlet-name>
</filter-mapping>
Filters can be associated with groups of servlets and static content using the
<url-pattern> style of filter mapping:
<filter-mapping>
<filter-name>Logging Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Here the Logging Filter is applied to all the servlets and static content pages in the Web application, because every request URI matches the ‘/*’ URL pattern.
<filter>
<filter-name>Image Filter</filter-name>
<filter-class>com.acme.ImageServlet</filter-class>
</filter>
Once a filter has been declared in the deployment descriptor, the assembler uses the <filter-mapping> element to define servlets and static resources in the Web application to which the filter is to be applied. Filters can be associated with a servlet using the <servlet-name> element. For example, the following code example maps the Image Filter filter to the ImageServlet servlet:
<filter-mapping>
<filter-name>Image Filter</filter-name>
<servlet-name>ImageServlet</servlet-name>
</filter-mapping>
Filters can be associated with groups of servlets and static content using the
<url-pattern> style of filter mapping:
<filter-mapping>
<filter-name>Logging Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Here the Logging Filter is applied to all the servlets and static content pages in the Web application, because every request URI matches the ‘/*’ URL pattern.
When processing a <filter-mapping> element using the <url-pattern> style, the container must determine whether the <url-pattern> matches the request URI using the path mapping rules defined in Chapter SRV.11, “Mapping Requests to Servlets”.
The order the container uses in building the chain of filters to be applied for a particular request URI is as follows:
1. First, the <url-pattern> matching filter mappings in the same order that these elements appear in the deployment descriptor.
2. Next, the <servlet-name> matching filter mappings in the same order that these elements appear in the deployment descriptor.
This requirement means that the container, when receiving an incoming request, processes the request as follows:
=> Identifies the target Web resource according to the rules of “Specification of Mappings” .
=> If there are filters matched by servlet name and the Web resource has a <servlet-name>, the container builds the chain of filters matching in the order declared in the deployment descriptor. The last filter in this chain corresponds to the last <servlet-name> matching filter and is the filter that invokes the target
Web resource.
=> If there are filters using <url-pattern> matching and the <url-pattern> matches the request URI according to the rules of Section, “Specification of Mappings”, the container builds the chain of <url-pattern> matched filters in the same order as declared in the deployment descriptor. The last filter in this chain is the last <url-pattern> matching filter in the deployment descriptor for this request URI. The last filter in this chain is the filter that invokes the first filter in the <servlet-name> matching chain, or invokes the target Web resource if there are none.
It is expected that high performanceWeb containers will cache filter chains so that they do not need to compute them on a per-request basis.
The order the container uses in building the chain of filters to be applied for a particular request URI is as follows:
1. First, the <url-pattern> matching filter mappings in the same order that these elements appear in the deployment descriptor.
2. Next, the <servlet-name> matching filter mappings in the same order that these elements appear in the deployment descriptor.
This requirement means that the container, when receiving an incoming request, processes the request as follows:
=> Identifies the target Web resource according to the rules of “Specification of Mappings” .
=> If there are filters matched by servlet name and the Web resource has a <servlet-name>, the container builds the chain of filters matching in the order declared in the deployment descriptor. The last filter in this chain corresponds to the last <servlet-name> matching filter and is the filter that invokes the target
Web resource.
=> If there are filters using <url-pattern> matching and the <url-pattern> matches the request URI according to the rules of Section, “Specification of Mappings”, the container builds the chain of <url-pattern> matched filters in the same order as declared in the deployment descriptor. The last filter in this chain is the last <url-pattern> matching filter in the deployment descriptor for this request URI. The last filter in this chain is the filter that invokes the first filter in the <servlet-name> matching chain, or invokes the target Web resource if there are none.
It is expected that high performanceWeb containers will cache filter chains so that they do not need to compute them on a per-request basis.
=> Filters and the RequestDispatcher
New for version 2.4 of the Java Servlet specification is the ability to configure filters to be invoked under request dispatcher forward() and include() calls. By using the new <dispatcher> element in the deployment descriptor, the developer can indicate for a filter-mapping whether he would like the filter to be applied to requests when:
1. The request comes directly from the client.
This is indicated by a <dispatcher> element with value REQUEST, or by the absence of any <dispatcher> elements.
2. The request is being processed under a request dispatcher representing the Web component matching the <url-pattern> or <servlet-name> using a forward() call.
This is indicated by a <dispatcher> element with value FORWARD.
3. The request is being processed under a request dispatcher representing the Web component matching the <url-pattern> or <servlet-name> using an include() call.
This is indicated by a <dispatcher> element with value INCLUDE.
4. The request is being processed with the error page mechanism specified in “Error Handling” to an error resource matching the <url-pattern>.
This is indicated by a <dispatcher> element with the value ERROR.
5. Or any combination of 1, 2, 3, or 4 above.
For example:
<filter-mapping>
<filter-name>Logging Filter</filter-name>
<url-pattern>/products/*</url-pattern>
</filter-mapping>
would result in the Logging Filter being invoked by client requests starting / products/... but not underneath a request dispatcher call where the request dispatcher has path commencing /products/.... The following code:
<filter-mapping>
<filter-name>Logging Filter</filter-name>
<servlet-name>ProductServlet</servlet-name>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>
would result in the Logging Filter not being invoked by client requests to the ProductServlet, nor underneath a request dispatcher forward() call to the ProductServlet, but would be invoked underneath a request dispatcher include() call where the request dispatcher has a name commencing ProductServlet.
Finally,
<filter-mapping>
<filter-name>Logging Filter</filter-name>
<url-pattern>/products/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
would result in the Logging Filter being invoked by client requests starting / products/... and underneath a request dispatcher forward() call where the request dispatcher has path commencing /products/....
1. The request comes directly from the client.
This is indicated by a <dispatcher> element with value REQUEST, or by the absence of any <dispatcher> elements.
2. The request is being processed under a request dispatcher representing the Web component matching the <url-pattern> or <servlet-name> using a forward() call.
This is indicated by a <dispatcher> element with value FORWARD.
3. The request is being processed under a request dispatcher representing the Web component matching the <url-pattern> or <servlet-name> using an include() call.
This is indicated by a <dispatcher> element with value INCLUDE.
4. The request is being processed with the error page mechanism specified in “Error Handling” to an error resource matching the <url-pattern>.
This is indicated by a <dispatcher> element with the value ERROR.
5. Or any combination of 1, 2, 3, or 4 above.
For example:
<filter-mapping>
<filter-name>Logging Filter</filter-name>
<url-pattern>/products/*</url-pattern>
</filter-mapping>
would result in the Logging Filter being invoked by client requests starting / products/... but not underneath a request dispatcher call where the request dispatcher has path commencing /products/.... The following code:
<filter-mapping>
<filter-name>Logging Filter</filter-name>
<servlet-name>ProductServlet</servlet-name>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>
would result in the Logging Filter not being invoked by client requests to the ProductServlet, nor underneath a request dispatcher forward() call to the ProductServlet, but would be invoked underneath a request dispatcher include() call where the request dispatcher has a name commencing ProductServlet.
Finally,
<filter-mapping>
<filter-name>Logging Filter</filter-name>
<url-pattern>/products/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
would result in the Logging Filter being invoked by client requests starting / products/... and underneath a request dispatcher forward() call where the request dispatcher has path commencing /products/....
No comments:
Post a Comment