askvity

How do you implement a custom filter?

Published in Web Filters 5 mins read

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 the init method exactly once after instantiating the filter. You can access initialization parameters using filterConfig.

  • 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's doFilter 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 to HttpServletRequest to access HTTP-specific functionality.
  • ServletResponse response: The response being generated. You typically cast this to HttpServletResponse 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 call chain.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:

  1. *`@WebFilter("/")`**: This annotation tells the servlet container to apply this filter to all URLs. You can use more specific URL patterns.
  2. doFilter(): This method logs the URL of each request before and after it's processed by the servlet.
  3. 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 the filterName 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.

Related Articles