web.xml
deployment descriptor.HTTP request doFilter doFilter doFilter +--------+ ==============> +------------+ ==========> +------------+ ==========> +------------+ ==========> +-------------+ | Client | | Filter (1) | | Filter (2) | | Filter (3) | | Servlet (1) | +--------+ <============== +------------+ <========== +------------+ <========== +------------+ <========== +-------------+ HTTP responseIn the above example:
filterChain.doFilter()
.load-on-startup
is provided, the servlet container alone decides when to load the filter class.
This decision is typically based on memory optimization and application startup performance considerations.static String myVar1 = "default";
).static { /* initialization code */ }
).init()
Method
init(FilterConfig filterConfig)
method is called immediately after the filter instance is created.
This method is called exactly once during the filter's lifetime and serves as the initialization phase where the filter can prepare itself for handling requests.FilterConfig
parameter provides access to the filter's configuration information, including initialization parameters and the servlet context.
It is a common practice to store the FilterConfig
instance in an instance variable so that it can be accessed later in the doFilter
method for retrieving initialization parameters or accessing the servlet context.init()
method throws a ServletException
, the filter will not be put into service, and the container will not route any requests to this filter.doFilter()
Method
doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
method is the core of filter functionality.
It is executed each time a new request is intercepted by the filter, making it the most frequently called method during the filter's lifetime.ServletRequest request
: contains the client's request data.ServletResponse response
: used to send data back to the client.FilterChain chain
: represents the remaining filters and the target servlet.FilterChain
parameter is crucial for maintaining the filter chain execution.
By calling chain.doFilter(request, response)
, the filter passes control to the next filter in the chain, or to the target servlet if this is the last filter.chain.doFilter()
, the request processing chain stops at that filter, and no subsequent filters or the target servlet will be executed.
In this case, the filter is responsible for generating a complete response to send back to the client.chain.doFilter()
, allowing them to modify the request before it reaches the servlet and modify the response after the servlet has processed it.destroy()
Method
destroy()
method is called when the servlet container decides that a filter instance is no longer needed and should be removed from service.
This method provides an opportunity for the filter to clean up any resources it may be holding.destroy()
method call can vary:destroy()
method helps prevent memory leaks and resource exhaustion.destroy()
is called, the filter instance will not receive any more requests, and the container may garbage collect the instance.package com.mtitek.filters.test1; import java.io.IOException; import jakarta.servlet.Filter; import jakarta.servlet.FilterChain; import jakarta.servlet.FilterConfig; import jakarta.servlet.ServletException; import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletResponse; public class MyFilter1 implements Filter { FilterConfig filterConfig; @Override public void init(FilterConfig filterConfig) throws ServletException { this.filterConfig = filterConfig; System.out.println("com.mtitek.filters.test1.MyFilter1 - " + this.filterConfig.getFilterName() + " : init(FilterConfig)"); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("com.mtitek.filters.test1.MyFilter1 - " + this.filterConfig.getFilterName() + " : doFilter(ServletRequest, ServletResponse, FilterChain) : Start"); filterChain.doFilter(servletRequest, servletResponse); System.out.println("com.mtitek.filters.test1.MyFilter1 - " + this.filterConfig.getFilterName() + " : doFilter(ServletRequest, ServletResponse, FilterChain) : End"); } @Override public void destroy() { System.out.println("com.mtitek.filters.test1.MyFilter1 - " + this.filterConfig.getFilterName() + " : destroy()"); } }The
FilterConfig
interface provides the following essential methods:String getFilterName()
: returns the logical name of the filter as defined in the deployment descriptor.ServletContext getServletContext()
: returns a reference to the ServletContext, providing access to the application scope and container information.String getInitParameter(String name)
: returns the value of the specified initialization parameter, or null if the parameter does not exist.Enumeration<String> getInitParameterNames()
: returns an Enumeration containing the names of all initialization parameters for this filter.web.xml
) involves two main elements that work together to define when and how filters are executed.
The servlet container uses these configurations to determine which filters to apply to incoming requests.<filter>
and <filter-mapping>
.
When processing a request, if the container finds a matching <filter-mapping>
element, it will look for the corresponding <filter>
element with the same filter name to determine which filter class to execute.<filter-mapping>
Element<filter-mapping> <filter-name> <!-- exactly one --> <url-pattern> OR <servlet-name> <!-- exactly one --> <dispatcher> <!-- [0 to 4] {REQUEST, FORWARD, INCLUDE, ERROR} -->
<filter>
element.
This creates the link between the filter mapping and the actual filter implementation./*
(matches all URLs), /admin/*
(matches all URLs starting with /admin/), or *.jsp
(matches all JSP files).
You cannot specify both <url-pattern>
and <servlet-name>
in the same mapping.<servlet-name>
element within a <servlet>
declaration.
This approach allows filtering specific servlets regardless of their URL mapping.forward()
method of the RequestDispatcher
class.
This is used when one servlet forwards a request to another servlet or JSP.include()
method of the RequestDispatcher
class.
This is used when including the output of another servlet or JSP in the current response.<error-page>
elements.
This allows filters to process error handling requests.<dispatcher>
elements in the same filter mapping.
This enables the filter to handle different types of request processing scenarios.<filter>
Element<filter> <description> <!-- 0 or more --> <display-name> <!-- 0 or more --> <icon> <!-- 0 or more --> <small-icon> <!-- 0 or 1 --> <large-icon> <!-- 0 or 1 --> <filter-name> <!-- exactly one --> <filter-class> <!-- exactly one --> <init-param> <!-- 0 or more --> <description> <!-- 0 or 1 --> <param-name> <!-- exactly one --> <param-value> <!-- exactly one -->Key elements include:
<filter-mapping>
element.
This name is also accessible programmatically through the FilterConfig.getFilterName()
method.jakarta.servlet.Filter
interface and be available in the web application's classpath.FilterConfig
object.
These parameters allow configuration of filter behavior without modifying the filter's source code.<url-pattern>
in a filter mapping or when it matches the configuration of a servlet whose name is specified in a <servlet-name>
element.
Multiple filters may match the same HTTP request, creating a filter chain.<url-pattern>
elements are executed before filters with matching <servlet-name>
elements.
Within this group, the execution order is determined by the sequence of <filter-mapping>
elements as they appear in the deployment descriptor.<servlet-name>
elements are executed.
Again, their execution order follows the order of <filter-mapping>
declarations in the deployment descriptor.web.xml
and an HTTP request to http://localhost:8181/test/MyServlet1
:<filter-mapping> <filter-name>MyFilter1</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>MyFilter3</filter-name> <servlet-name>MyServlet1</servlet-name> </filter-mapping> <filter-mapping> <filter-name>MyFilter2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>The execution order will be: MyFilter1 → MyFilter2 → MyFilter3 → MyServlet1
/*
) and appears first among URL pattern mappingsMyServlet1
), and servlet name mappings execute after URL pattern mappingsFilterConfig
object passed to the init()
method.FilterConfig
interface provides two methods for working with initialization parameters:String getInitParameter(String parameterName) Enumeration<String> getInitParameterNames()The
getInitParameter()
method returns the value of the specified parameter, or null
if the parameter does not exist.
The getInitParameterNames()
method returns an enumeration of all parameter names, which is useful for iterating through all available parameters.<filter>
element using <init-param>
sub-elements:<init-param> <param-name>PARAM_NAME</param-name> <param-value>PARAM_VALUE</param-value> </init-param>Each
<init-param>
element defines a name-value pair that will be available to the filter during its initialization and execution phases.<filter> <filter-name>MyFilter1</filter-name> <filter-class>com.mtitek.filters.test1.MyFilter1</filter-class> <init-param> <param-name>filter1_paramname_1</param-name> <param-value>filter1_paramvalue_1</param-value> </init-param> <init-param> <param-name>filter1_paramname_2</param-name> <param-value>filter1_paramvalue_2</param-value> </init-param> </filter>
package com.mtitek.filters.test1; import java.io.IOException; import java.util.Enumeration; import jakarta.servlet.Filter; import jakarta.servlet.FilterChain; import jakarta.servlet.FilterConfig; import jakarta.servlet.ServletException; import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletResponse; public class MyFilter1 implements Filter { FilterConfig filterConfig; @Override public void init(FilterConfig filterConfig) throws ServletException { this.filterConfig = filterConfig; } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { Enumeration<String> initParameterNames = this.filterConfig.getInitParameterNames(); while (initParameterNames.hasMoreElements()) { String initParameterName = (String) initParameterNames.nextElement(); String initParameterValue = this.filterConfig.getInitParameter(initParameterName); System.out.println(initParameterName + " : " + initParameterValue); } filterChain.doFilter(servletRequest, servletResponse); } @Override public void destroy() { } }
filter1_paramname_1 : filter1_paramvalue_1 filter1_paramname_2 : filter1_paramvalue_2