Core Concepts of Interceptors
In Spring applications, interceptors serve as middleware components designed to execute custom logic before or after HTTP requests are processed. Unlike Aspect-Oriented Programming (AOP), which targets method-level cross-cutting concerns, interceptors specifically focus on the request processing pipeline.
Interceptor Interface Implementation
To create an interceptor in Spring, implement the HandlerInterceptor interface, which provides three callback methods:
preHandle: Executed before the controller method runs, allowing request preprocessingpostHandle: Runs after controller execution but before view renderingafterCompletion: Called after the entire request processing cycle completes, suitable for cleanup operations
Registration and Configuration
Interceptors are registered by implementing WebMvcConfigurer and overriding the addInterceptors method:
@Configuration
public class MvcConfiguration implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthenticationInterceptor())
.addPathPatterns("/secure/**")
.excludePathPatterns("/public/**");
}
}
Practical Interceptor Implemantation
Here's a concrete implemantation example:
@Component
public class AuthenticationInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) {
String authHeader = req.getHeader("X-Auth-Token");
if (authHeader == null || authHeader.isBlank()) {
res.setStatus(HttpStatus.UNAUTHORIZED.value());
return false;
}
return validateToken(authHeader);
}
@Override
public void postHandle(HttpServletRequest req, HttpServletResponse res,
Object handler, ModelAndView modelAndView) {
// Post-processing logic before view rendering
}
@Override
public void afterCompletion(HttpServletRequest req, HttpServletResponse res,
Object handler, Exception exception) {
if (exception != null) {
logError(req, exception);
}
cleanupResources();
}
private boolean validateToken(String token) {
// Token validation logic
return true;
}
private void logError(HttpServletRequest req, Exception ex) {
System.err.println("Error processing " + req.getRequestURI() + ": " + ex.getMessage());
}
private void cleanupResources() {
// Resource cleanup operations
}
}
Distinguishing Interceptors from AOP
While both mechanisms address cross-cutting concerns, they differ in scope and application:
Scope and Focus:
- Interceptors operate within the web request lifecycle, targeting HTTP-specific operations
- AOP provides broader application-level concern management across methods, objects, and properties
Granularity:
- Interceptors work at the request level with coarse granularity
- AOP offers fine-grained control through pointcut expressions
Implementation Context:
- Interceptors depend on Spring MVC infrastructure
- AOP can function independently across various frameworks
Common Use Cases
Interceptors are particularly effective for:
- Authentication and authorization enforcement
- Request/response logging and monitoring
- Input validation and sanitization
- Session management and security checks
Advanced Interceptor Example
This enhanced interceptor performs authentication validation and comprehensive request lifecycle management:
@Component
public class ComprehensiveInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) {
String credentials = req.getHeader("Authorization");
if (!isValidCredentials(credentials)) {
res.setStatus(HttpStatus.UNAUTHORIZED.value());
return false;
}
return true;
}
@Override
public void afterCompletion(HttpServletRequest req, HttpServletResponse res,
Object handler, Exception ex) {
if (ex != null) {
res.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
System.err.println("Processing failed for " + req.getRequestURI() + ": " + ex.getMessage());
} else {
System.out.println("Successfully processed " + req.getRequestURI());
}
}
private boolean isValidCredentials(String authData) {
// Authentication validation implementation
return authData != null && !authData.isEmpty();
}
}
This pattern enables robust request handling with proper authentication checks and detailed operational logging throughout the request lifecycle.