Understanding Servlet Filters and Spring MVC Interceptors

Servlet Filters

Filters are a core component of the Java Servlet specification, operating within the servlet container to pre-process requests and post-process responses. They execute before a request reaches a servlet and after the servlet generates a response, enabling tasks like logging, authentication, and data transformation.

Core Conecpts

  • Lifecycle Management: The servlet container manages filter instances through init(), doFilter(), and destroy() methods.
  • Filter Chain: Multiple filters can be chained sequentially. The container invokes each filter's doFilter() method, passing control via FilterChain.doFilter() to proceed to the next filter or target servlet.
  • Request/Response Modification: Filters can wrap or alter ServletRequest and ServletResponse objects but typically do not generate responses directly.

Implementation Example

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(urlPatterns = "/api/*")
public class AuthFilter implements Filter {
    @Override
    public void init(FilterConfig config) throws ServletException {
        // Initialization logic
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("Authentication check");
        // Custom logic (e.g., validate session)
        chain.doFilter(req, resp);
        System.out.println("Post-processing response");
    }

    @Override
    public void destroy() {
        // Cleanup resources
    }
}

Common Use Cases

  • Access control and authorization
  • Logging request/response details
  • Modifying request headers or encoding
  • Response compression or caching

Key Considerations

  • Order of execution in filter chains
  • Proper resource cleanup in destroy()
  • Exception handling to avoid breaking the request flow

Spring MVC Interceptors

Interceptors are specific to Spring MVC, providing fine-grained control over request processing within the DispatcherServlet flow. They intercept requests before and after controller execution, leveraging Spring's context for advanced functionality.

Core Concepts

  • Integration with DispatcherServlet: Interceptors hook into Spring MVC's request handling pipeline, operating between DispatcherServlet and controller methods.
  • Handler Mapping: Spring resolves the appropriate controller via handler mapping before interceptor execution.
  • Interceptor Chain: Multiple interceptors execute in configured order, with methods preHandle(), postHandle(), and afterCompletion().
  • Method-Level Control: Interceptors can target specific controller methods, accessing handler metadata and model data.

Implementation Example

import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class TimingInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) {
        req.setAttribute("startTime", System.currentTimeMillis());
        return true; // Continue processing
    }

    @Override
    public void postHandle(HttpServletRequest req, HttpServletResponse res, Object handler, ModelAndView mv) {
        Long start = (Long) req.getAttribute("startTime");
        System.out.println("Request duration: " + (System.currentTimeMillis() - start) + "ms");
    }

    @Override
    public void afterCompletion(HttpServletRequest req, HttpServletResponse res, Object handler, Exception ex) {
        // Cleanup or final logging
    }
}

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MvcConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new TimingInterceptor()).addPathPatterns("/**");
    }
}

Common Use Cases

  • Method-level security checks
  • Performance monitoring and metrics
  • Transaction management
  • Content negotiation and locale resolution

Key Considerations

  • preHandle() return value controls continuation (true/false)
  • Exception handling within interceptor methods
  • Ordering in interceptor chains

Comparison of Filters and Interceptors

Similarities

  • Both enable pre-processing and post-processing of HTTP requests/responses
  • Support logging, security, and data manipulation
  • Configurable via annotations or XML

Differences

  • Framework/Standard: Filters are part of the Servlet specification; interceptors are Spring MVC components.
  • Execution Layer: Filters operate at the servlet container level; interceptors work within Spring's DispatcherServlet flow.
  • Granularity: Filters apply broadly to URL patterns; interceptors can target specific controller methods.
  • Context Access: Filters use Servlet API only; interceptors can access Spring context, handler metadata, and model data.
  • Exception Handling: Filters require manual exception handling; interceptors integrate with Spring's exception resolution.

Selection Guidelines

  • Use filters for container-level processing independent of Spring (e.g., compression, encoding).
  • Use interceptors for Spring-aware processing rqeuiring method-level control or Spring context data.

Logging Implementation Examples

Database Schema

CREATE TABLE operation_log (
    id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
    class_name VARCHAR(100),
    method_name VARCHAR(100),
    method_description VARCHAR(200),
    parameters TEXT,
    return_value TEXT,
    operator_id INT UNSIGNED,
    operation_time DATETIME,
    duration_ms BIGINT
);

Custom Annotation

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OperationLog {
    String description() default "";
}

AOP-Based Logging

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;

@Aspect
@Component
public class LoggingAspect {
    @Autowired
    private HttpServletRequest currentRequest;
    
    @Pointcut("@annotation(OperationLog)")
    public void loggedOperations() {}
    
    @Around("loggedOperations()")
    public Object logOperation(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        Object result;
        try {
            result = joinPoint.proceed();
            long duration = System.currentTimeMillis() - start;
            // Persist log with duration and result
        } catch (Exception e) {
            // Log exception details
            throw e;
        }
        return result;
    }
}

Interceptor-Based Logging

import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class AuditInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) {
        if (handler instanceof HandlerMethod) {
            HandlerMethod method = (HandlerMethod) handler;
            if (method.hasMethodAnnotation(OperationLog.class)) {
                req.setAttribute("auditStart", System.currentTimeMillis());
            }
        }
        return true;
    }
    
    @Override
    public void afterCompletion(HttpServletRequest req, HttpServletResponse res, Object handler, Exception ex) {
        Long start = (Long) req.getAttribute("auditStart");
        if (start != null) {
            long duration = System.currentTimeMillis() - start;
            // Persist audit log with duration and exception status
        }
    }
}

Execution Order with Interceptors and AOP

When both interceptors and AOP aspects are applied:

  1. Interceptor preHandle()
  2. AOP @Before advice
  3. Controller method execution
  4. AOP @AfterReturning advice
  5. Interceptor postHandle()
  6. Interceptor afterCompletion()
  7. AOP @After (finally) advice

AOP @Around advice execution depends on proceed() invocation placement. @AfterThrowing advice executes if exceptions occur, before afterCompletion().

Tags: java servlet Spring MVC Filters Interceptors

Posted on Sun, 10 May 2026 04:21:31 +0000 by ajcether