You implement a custom filter by creating a class that implements the Filter
interface and defining the logic for request and response processing within the doFilter()
method.
Here's a breakdown of the steps involved, along with a simple example:
1. Implement the Filter
Interface
Create a Java class that implements the javax.servlet.Filter
interface. This interface defines three methods you must implement:
-
init(FilterConfig filterConfig)
: Called by the servlet container to indicate to a filter that it is being placed into service. The servlet container calls theinit
method exactly once after instantiating the filter. You can access initialization parameters usingfilterConfig
. -
doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
: The core method where the filtering logic resides. This method is invoked every time a request/response is passed through the filter. -
destroy()
: Called by the servlet container to indicate to a filter that it is being taken out of service. This method is only called once all threads within the filter'sdoFilter
method have exited, or after a timeout period has passed.
2. Implement the doFilter()
Method
The doFilter()
method is where you implement the filter's core logic. This method takes three arguments:
ServletRequest request
: The request being processed. You typically cast this toHttpServletRequest
to access HTTP-specific functionality.ServletResponse response
: The response being generated. You typically cast this toHttpServletResponse
for HTTP-specific features.FilterChain chain
: An object that allows the filter to pass the request and response to the next filter in the chain (or to the target servlet if it's the last filter). It's crucial to callchain.doFilter(request, response)
if you want the request to continue processing.
3. Configure the Filter in web.xml
(or using Annotations)
You need to tell the servlet container about your filter and which URLs it should apply to. This can be done in two main ways:
-
web.xml (Deployment Descriptor): Define the filter and its mapping in the
web.xml
file (or equivalent deployment descriptor). This is the traditional approach. -
Annotations (Servlet 3.0+): Use the
@WebFilter
annotation on your filter class. This is a more modern and convenient approach.
Example: Simple Logging Filter (using Annotations)
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@WebFilter("/*") // Applies to all URLs
public class LoggingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// Initialization code (optional)
System.out.println("LoggingFilter initialized");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String url = httpRequest.getRequestURL().toString();
System.out.println("Request received for: " + url);
// Pass the request and response to the next filter in the chain
chain.doFilter(request, response);
System.out.println("Response sent for: " + url);
}
@Override
public void destroy() {
// Cleanup code (optional)
System.out.println("LoggingFilter destroyed");
}
}
Explanation:
- *`@WebFilter("/")`**: This annotation tells the servlet container to apply this filter to all URLs. You can use more specific URL patterns.
doFilter()
: This method logs the URL of each request before and after it's processed by the servlet.chain.doFilter(request, response)
: This line is essential. It passes the request and response to the next filter in the chain (or to the servlet itself). If you don't call this, the request processing will stop at the filter.
Example: Configuring in web.xml
<web-app>
<filter>
<filter-name>LoggingFilter</filter-name>
<filter-class>com.example.LoggingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>LoggingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
Explanation:
<filter>
: Defines the filter with a name and the fully qualified class name.<filter-mapping>
: Maps the filter to a URL pattern.
Key Considerations:
- Filter Order: Filters are applied in the order they are declared in
web.xml
or based on thefilterName
order if annotations are used and the container supports ordering via name. The order matters if you have multiple filters that depend on each other. - Error Handling: Handle exceptions carefully in your filter logic. You might want to log errors and/or redirect the user to an error page.
- Performance: Filters can impact performance, so keep them as efficient as possible. Avoid expensive operations in the
doFilter()
method. - Security: Be mindful of security vulnerabilities. For example, prevent cross-site scripting (XSS) by sanitizing user input.
In summary, implementing a custom filter involves creating a class that implements the Filter
interface, writing the filtering logic in the doFilter()
method, and configuring the filter using annotations or the web.xml
file. Remember to always call chain.doFilter(request, response)
to allow the request to continue processing.