The Servlet filters are components that can intercept an incoming request and outgoing response before it gets to a Java Servlet. The filters can be chained together through the configuration of the web deployment descriptor or through the annotations. Filters do not normally generate the content, rather they are designed to transform, modify, or adapt a request around a resource. The filters can be used for logging, security, and performance monitoring.
A Servlet filter implements the
javax.servlet.Filter
interface. A Servlet filter implements the doFilter()
method, which takes three arguments: ServletRequest
, ServletResponse
, and javax.servlet.FilterChain
.
FilterChain
is a simple interface with one method doFilter()
, which is the way to transfer the control to the next filter in the chain.
Let's review, together, a working example as follows:
package je7hb.servlets.simple; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.annotation.WebInitParam; import javax.servlet.http.*; import java.io.IOException; import java.util.Date; @WebFilter(filterName = "MySimpleFilterLogger", urlPatterns = {"/*"}, initParams = {@WebInitParam(name = "fruit", value = "Pear"),}) public class SimpleLoggingFilter implements Filter { private FilterConfig filterConfig; public void init(FilterConfig filterConfig) { System.out.printf("init() on %s "+ "Metadata filter name=%s ", getClass().getSimpleName(), filterConfig.getFilterName()); this.filterConfig = filterConfig; } public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException { System.out.printf("doFilter() on %s at %s ", this.getClass().getSimpleName(), new Date()); System.out.printf("init parameter on 'fruit' is %s ", filterConfig.getInitParameter("fruit")); filterChain.doFilter(request, response); } public void destroy() { System.out.printf("destroy() on %s ", getClass().getSimpleName()); } }
This filter
SimpleLoggingFilter
is annotated by the name MySimpleFilterLogger
with the URL patterns (/*
) such that it intercepts all the requests. The class dumps the output to the console output. A filter has initialization and destruction methods, which web container invokes as the web application starts up or shuts down accordingly.
Inside the doFilter()
method, executing the filterChain.doFilter()
method is the critical part, because that call passes the control back to web container, and then it causes the execution of the next filter in line or the actual resource.
A table of the
@WebFilter
attributes is as follows:
If you prefer not to declare the annotations, then the filter must be declared in a deployment descriptor, the web.xml
file. An XML fragment that configures the filter is as follows:
<filter> <filter-name>MySimpleFilterLogger</filter-name> <filter-class> je7hb.servlets.simple.SimpleLoggingFilter </filter-class> <init-param> <param-name>fruit</param-name> <param-value>strawberry</param-value> </init-param> </filter> <filter-mapping> <filter-name>MySimpleFilterLogger</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
<filter>
and <filter-mapping>
are direct subelements of the <web-app>
element, and they are visually similar to the Servlet mappings.
The <filter>
element declares the filter name, fully qualified class name, and optionally the initialization parameters. The <filter-mapping>
element associates a filter name with a set of the URL patterns.
To implement a security servlet filter, the logic of the doFilter()
method would change to only execute the next filter on completion of a check.
The following code is an example of securing a resource with a Servlet filter:
public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest req2 = (HttpServletRequest)req; HttpServletResponse res2 = (HttpServletResponse)res; if (req2.getUserPrincipal().getName() .equals("admin")) { filterChain.doFilter(req, res); } else { res2.sendError(HttpServletResponse.SC_UNAUTHORIZED); } }
The previous filter code allows the requests to propagate to the next filter or resource, only if the incoming request has the JavaEE user principal authorization. If the request is unauthorized, the filter sends the client to the error page, if defined. Notice how we recast the Servlet and response objects to HttpServletRequest
and HttpServletResponse
.
Obviously the Java EE web container will need to have security principals and realms defined externally to the web application in order for this filter to work.
3.138.37.20